| @@ -2,7 +2,7 @@ | |||||
| <h1><img src="public/img/favicon.png" alt="logo" width="30" height="30">AiForge - 启智AI开发协作平台</h1> | <h1><img src="public/img/favicon.png" alt="logo" width="30" height="30">AiForge - 启智AI开发协作平台</h1> | ||||
| [](https://git.openi.org.cn/OpenI/aiforge/releases/latest) | |||||
| [](https://openi.pcl.ac.cn/OpenI/aiforge/releases/latest) | |||||
| [](https://opensource.org/licenses/MIT) | [](https://opensource.org/licenses/MIT) | ||||
| @@ -10,7 +10,7 @@ | |||||
| 启智AI开发协作平台是一个在线Web应用,旨在为人工智能算法、模型开发提供在线协同工作环境,它提供了<b>代码托管、数据集管理与共享、免费云端算力资源支持(GPU/NPU)、共享镜像</b>等功能。 | 启智AI开发协作平台是一个在线Web应用,旨在为人工智能算法、模型开发提供在线协同工作环境,它提供了<b>代码托管、数据集管理与共享、免费云端算力资源支持(GPU/NPU)、共享镜像</b>等功能。 | ||||
| [启智AI开发协作平台](https://git.openi.org.cn) 是使用本项目构建的在线服务,您可以直接点击链接访问试用。 | |||||
| [启智AI开发协作平台](https://openi.pcl.ac.cn) 是使用本项目构建的在线服务,您可以直接点击链接访问试用。 | |||||
| 本项目是基于[Gitea](https://github.com/go-gitea/gitea)发展而来的,我们对其进行了Fork并基于此扩展了人工智能开发中需要的功能,如数据集管理和模型训练等。对于和代码托管相关的功能,您可以参考[Gitea的文档](https://docs.gitea.io/zh-cn/)。 | 本项目是基于[Gitea](https://github.com/go-gitea/gitea)发展而来的,我们对其进行了Fork并基于此扩展了人工智能开发中需要的功能,如数据集管理和模型训练等。对于和代码托管相关的功能,您可以参考[Gitea的文档](https://docs.gitea.io/zh-cn/)。 | ||||
| @@ -20,7 +20,7 @@ | |||||
| 后端服务涵盖了AI模型开发流水线,包括代码协同开发、数据管理、模型调试、训练、推理和部署等(*目前尚未支持模型部署*)。在不同的开发阶段,我们还将提供丰富的开发工具供用户使用,如数据标注、数据筛选、模型转换、模型压缩、代码检测等。我们也欢迎社区提供更多丰富的工具接入,提高利用平台进行开发的效率。 | 后端服务涵盖了AI模型开发流水线,包括代码协同开发、数据管理、模型调试、训练、推理和部署等(*目前尚未支持模型部署*)。在不同的开发阶段,我们还将提供丰富的开发工具供用户使用,如数据标注、数据筛选、模型转换、模型压缩、代码检测等。我们也欢迎社区提供更多丰富的工具接入,提高利用平台进行开发的效率。 | ||||
|  |  | ||||
| ## 在线服务使用 | ## 在线服务使用 | ||||
| 本项目的在线服务平台的详细使用帮助文档,可参阅本项目[百科](https://git.openi.org.cn/OpenI/aiforge/wiki)内容。 | |||||
| 本项目的在线服务平台的详细使用帮助文档,可参阅本项目[百科](https://openi.pcl.ac.cn/OpenI/aiforge/wiki)内容。 | |||||
| - 如何创建账号 | - 如何创建账号 | ||||
| - 如何创建组织及管理成员权限 | - 如何创建组织及管理成员权限 | ||||
| - 如何创建项目仓库 | - 如何创建项目仓库 | ||||
| @@ -39,22 +39,22 @@ | |||||
| [从源代码安装说明](https://docs.gitea.io/zh-cn/install-from-source/) | [从源代码安装说明](https://docs.gitea.io/zh-cn/install-from-source/) | ||||
| ## 授权许可 | ## 授权许可 | ||||
| 本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://git.openi.org.cn/OpenI/aiforge/src/branch/develop/LICENSE) 文件中。 | |||||
| 本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://openi.pcl.ac.cn/OpenI/aiforge/src/branch/develop/LICENSE) 文件中。 | |||||
| ## 需要帮助? | ## 需要帮助? | ||||
| 如果您在使用或者开发过程中遇到问题,可以在以下渠道咨询: | 如果您在使用或者开发过程中遇到问题,可以在以下渠道咨询: | ||||
| - 点击[这里](https://git.openi.org.cn/OpenI/aiforge/issues)在线提交问题(点击页面右上角绿色按钮**创建任务**) | |||||
| - 点击[这里](https://openi.pcl.ac.cn/OpenI/aiforge/issues)在线提交问题(点击页面右上角绿色按钮**创建任务**) | |||||
| - 加入微信群实时交流,获得进一步的支持 | - 加入微信群实时交流,获得进一步的支持 | ||||
| <img src="https://git.openi.org.cn/OpenI/aiforge/wiki/raw/img/wechatgroup.jpg" width=200px /> | |||||
| <img src="https://openi.pcl.ac.cn/OpenI/aiforge/wiki/raw/img/wechatgroup.jpg" width=200px /> | |||||
| ## 启智社区小白训练营: | ## 启智社区小白训练营: | ||||
| - 结合案例给大家详细讲解如何使用社区平台,帮助无技术背景的小白成长为启智社区达人 (https://git.openi.org.cn/zeizei/OpenI_Learning) | |||||
| - 结合案例给大家详细讲解如何使用社区平台,帮助无技术背景的小白成长为启智社区达人 (https://openi.pcl.ac.cn/zeizei/OpenI_Learning) | |||||
| ## 平台引用 | ## 平台引用 | ||||
| 如果本平台对您的科研工作提供了帮助,可在论文致谢中加入: | 如果本平台对您的科研工作提供了帮助,可在论文致谢中加入: | ||||
| 英文版:```Thanks for the support provided by OpenI Community (https://git.openi.org.cn).``` | |||||
| 中文版:```感谢启智社区提供的技术支持(https://git.openi.org.cn)。``` | |||||
| 英文版:```Thanks for the support provided by OpenI Community (https://openi.pcl.ac.cn).``` | |||||
| 中文版:```感谢启智社区提供的技术支持(https://openi.pcl.ac.cn)。``` | |||||
| 如果您的成果中引用了本平台,也欢迎在下述开源项目中提交您的成果信息: | 如果您的成果中引用了本平台,也欢迎在下述开源项目中提交您的成果信息: | ||||
| https://git.openi.org.cn/OpenIOSSG/references | |||||
| https://openi.pcl.ac.cn/OpenIOSSG/references | |||||
| @@ -14,6 +14,7 @@ import ( | |||||
| type AiModelManage struct { | type AiModelManage struct { | ||||
| ID string `xorm:"pk" json:"id"` | ID string `xorm:"pk" json:"id"` | ||||
| Name string `xorm:"INDEX NOT NULL" json:"name"` | Name string `xorm:"INDEX NOT NULL" json:"name"` | ||||
| ModelType int `xorm:"NULL" json:"modelType"` | |||||
| Version string `xorm:"NOT NULL" json:"version"` | Version string `xorm:"NOT NULL" json:"version"` | ||||
| VersionCount int `xorm:"NOT NULL DEFAULT 0" json:"versionCount"` | VersionCount int `xorm:"NOT NULL DEFAULT 0" json:"versionCount"` | ||||
| New int `xorm:"NOT NULL" json:"new"` | New int `xorm:"NOT NULL" json:"new"` | ||||
| @@ -287,6 +288,37 @@ func ModifyModelDescription(id string, description string) error { | |||||
| return nil | return nil | ||||
| } | } | ||||
| func ModifyLocalModel(id string, name, label, description string, engine int) error { | |||||
| var sess *xorm.Session | |||||
| sess = x.ID(id) | |||||
| defer sess.Close() | |||||
| re, err := sess.Cols("name", "label", "description", "engine").Update(&AiModelManage{ | |||||
| Description: description, | |||||
| Name: name, | |||||
| Label: label, | |||||
| Engine: int64(engine), | |||||
| }) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| log.Info("success to update description from db.re=" + fmt.Sprint((re))) | |||||
| return nil | |||||
| } | |||||
| func ModifyModelSize(id string, size int64) error { | |||||
| var sess *xorm.Session | |||||
| sess = x.ID(id) | |||||
| defer sess.Close() | |||||
| re, err := sess.Cols("size").Update(&AiModelManage{ | |||||
| Size: size, | |||||
| }) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| log.Info("success to update size from db.re=" + fmt.Sprint((re))) | |||||
| return nil | |||||
| } | |||||
| func ModifyModelStatus(id string, modelSize int64, status int, modelPath string, statusDesc string) error { | func ModifyModelStatus(id string, modelSize int64, status int, modelPath string, statusDesc string) error { | ||||
| var sess *xorm.Session | var sess *xorm.Session | ||||
| sess = x.ID(id) | sess = x.ID(id) | ||||
| @@ -134,7 +134,8 @@ func (a *Attachment) S3DownloadURL() string { | |||||
| if a.Type == TypeCloudBrainOne { | if a.Type == TypeCloudBrainOne { | ||||
| url, _ = storage.Attachments.PresignedGetURL(setting.Attachment.Minio.BasePath+AttachmentRelativePath(a.UUID), a.Name) | url, _ = storage.Attachments.PresignedGetURL(setting.Attachment.Minio.BasePath+AttachmentRelativePath(a.UUID), a.Name) | ||||
| } else if a.Type == TypeCloudBrainTwo { | } else if a.Type == TypeCloudBrainTwo { | ||||
| url, _ = storage.ObsGetPreSignedUrl(a.UUID, a.Name) | |||||
| objectName := strings.TrimPrefix(path.Join(setting.BasePath, path.Join(a.UUID[0:1], a.UUID[1:2], a.UUID, a.Name)), "/") | |||||
| url, _ = storage.ObsGetPreSignedUrl(objectName, a.Name) | |||||
| } | } | ||||
| return url | return url | ||||
| @@ -550,7 +551,6 @@ func AttachmentsByDatasetOption(datasets []int64, opts *SearchDatasetOptions) ([ | |||||
| ) | ) | ||||
| } | } | ||||
| attachments := make([]*Attachment, 0) | attachments := make([]*Attachment, 0) | ||||
| if err := sess.Table(&Attachment{}).Where(cond).Desc("id"). | if err := sess.Table(&Attachment{}).Where(cond).Desc("id"). | ||||
| Find(&attachments); err != nil { | Find(&attachments); err != nil { | ||||
| @@ -291,12 +291,30 @@ func (task *Cloudbrain) IsRunning() bool { | |||||
| status == string(JobRunning) || status == GrampusStatusRunning | status == string(JobRunning) || status == GrampusStatusRunning | ||||
| } | } | ||||
| func (task *Cloudbrain) IsUserHasRight(user *User) bool { | |||||
| if user == nil { | |||||
| return false | |||||
| } | |||||
| return user.IsAdmin || user.ID == task.UserID | |||||
| } | |||||
| func ConvertDurationToStr(duration int64) string { | func ConvertDurationToStr(duration int64) string { | ||||
| if duration <= 0 { | if duration <= 0 { | ||||
| return DURATION_STR_ZERO | return DURATION_STR_ZERO | ||||
| } | } | ||||
| return util.AddZero(duration/3600) + ":" + util.AddZero(duration%3600/60) + ":" + util.AddZero(duration%60) | return util.AddZero(duration/3600) + ":" + util.AddZero(duration%3600/60) + ":" + util.AddZero(duration%60) | ||||
| } | } | ||||
| func ConvertStrToDuration(trainJobDuration string) int64 { | |||||
| trainJobDurationList := strings.Split(trainJobDuration, ":") | |||||
| if len(trainJobDurationList) == 3 { | |||||
| i, _ := strconv.ParseInt(trainJobDurationList[0], 10, 64) | |||||
| j, _ := strconv.ParseInt(trainJobDurationList[1], 10, 64) | |||||
| k, _ := strconv.ParseInt(trainJobDurationList[2], 10, 64) | |||||
| return i*3600 + j*60 + k | |||||
| } else { | |||||
| return 0 | |||||
| } | |||||
| } | |||||
| func IsTrainJobTerminal(status string) bool { | func IsTrainJobTerminal(status string) bool { | ||||
| return status == string(ModelArtsTrainJobCompleted) || status == string(ModelArtsTrainJobFailed) || status == string(ModelArtsTrainJobKilled) || status == GrampusStatusFailed || status == GrampusStatusStopped || status == GrampusStatusSucceeded | return status == string(ModelArtsTrainJobCompleted) || status == string(ModelArtsTrainJobFailed) || status == string(ModelArtsTrainJobKilled) || status == GrampusStatusFailed || status == GrampusStatusStopped || status == GrampusStatusSucceeded | ||||
| @@ -1589,9 +1607,23 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | |||||
| } | } | ||||
| } | } | ||||
| if (opts.AiCenter) != "" { | if (opts.AiCenter) != "" { | ||||
| cond = cond.And( | |||||
| builder.Like{"cloudbrain.ai_center", opts.AiCenter}, | |||||
| ) | |||||
| if opts.AiCenter == AICenterOfCloudBrainOne { | |||||
| cond = cond.And( | |||||
| builder.Eq{"cloudbrain.type": TypeCloudBrainOne}, | |||||
| ) | |||||
| } else if opts.AiCenter == AICenterOfCloudBrainTwo { | |||||
| cond = cond.And( | |||||
| builder.Eq{"cloudbrain.type": TypeCloudBrainTwo}, | |||||
| ) | |||||
| } else if opts.AiCenter == AICenterOfChengdu { | |||||
| cond = cond.And( | |||||
| builder.Eq{"cloudbrain.type": TypeCDCenter}, | |||||
| ) | |||||
| } else { | |||||
| cond = cond.And( | |||||
| builder.Like{"cloudbrain.ai_center", opts.AiCenter}, | |||||
| ) | |||||
| } | |||||
| } | } | ||||
| if (opts.Cluster) != "" { | if (opts.Cluster) != "" { | ||||
| if opts.Cluster == "resource_cluster_openi" { | if opts.Cluster == "resource_cluster_openi" { | ||||
| @@ -1968,7 +2000,7 @@ func UpdateTrainJobVersion(job *Cloudbrain) error { | |||||
| func updateJobTrainVersion(e Engine, job *Cloudbrain) error { | func updateJobTrainVersion(e Engine, job *Cloudbrain) error { | ||||
| var sess *xorm.Session | var sess *xorm.Session | ||||
| sess = e.Where("job_id = ? AND version_name=?", job.JobID, job.VersionName) | sess = e.Where("job_id = ? AND version_name=?", job.JobID, job.VersionName) | ||||
| _, err := sess.Cols("status", "train_job_duration", "duration", "start_time", "end_time", "created_unix").Update(job) | |||||
| _, err := sess.Cols("status", "train_job_duration", "duration", "start_time", "end_time", "created_unix", "ai_center").Update(job) | |||||
| return err | return err | ||||
| } | } | ||||
| @@ -2030,10 +2062,17 @@ func GetStoppedJobWithNoStartTimeEndTime() ([]*Cloudbrain, error) { | |||||
| cloudbrains := make([]*Cloudbrain, 0) | cloudbrains := make([]*Cloudbrain, 0) | ||||
| return cloudbrains, x.SQL("select * from cloudbrain where status in (?,?,?,?,?,?,?) and (start_time is null or end_time is null) limit 100", ModelArtsTrainJobCompleted, ModelArtsTrainJobFailed, ModelArtsTrainJobKilled, ModelArtsStopped, JobStopped, JobFailed, JobSucceeded).Find(&cloudbrains) | return cloudbrains, x.SQL("select * from cloudbrain where status in (?,?,?,?,?,?,?) and (start_time is null or end_time is null) limit 100", ModelArtsTrainJobCompleted, ModelArtsTrainJobFailed, ModelArtsTrainJobKilled, ModelArtsStopped, JobStopped, JobFailed, JobSucceeded).Find(&cloudbrains) | ||||
| } | } | ||||
| func GetC2NetWithAiCenterWrongJob() ([]*Cloudbrain, error) { | |||||
| cloudbrains := make([]*Cloudbrain, 0) | |||||
| return cloudbrains, x. | |||||
| In("status", ModelArtsTrainJobCompleted, ModelArtsTrainJobFailed, ModelArtsTrainJobKilled, ModelArtsStopped, JobStopped, JobFailed, JobSucceeded). | |||||
| Where("type = ?", TypeC2Net). | |||||
| Find(&cloudbrains) | |||||
| } | |||||
| func GetModelSafetyTestTask() ([]*Cloudbrain, error) { | func GetModelSafetyTestTask() ([]*Cloudbrain, error) { | ||||
| cloudbrains := make([]*Cloudbrain, 0) | cloudbrains := make([]*Cloudbrain, 0) | ||||
| sess := x.Where("job_type = ?", string(JobTypeModelSafety)) | |||||
| sess := x.Where("job_type=?", string(JobTypeModelSafety)) | |||||
| err := sess.Find(&cloudbrains) | err := sess.Find(&cloudbrains) | ||||
| return cloudbrains, err | return cloudbrains, err | ||||
| } | } | ||||
| @@ -2285,10 +2324,23 @@ func CloudbrainAllStatic(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, er | |||||
| } | } | ||||
| // sess.OrderBy("cloudbrain.created_unix DESC") | // sess.OrderBy("cloudbrain.created_unix DESC") | ||||
| cloudbrains := make([]*CloudbrainInfo, 0, setting.UI.IssuePagingNum) | cloudbrains := make([]*CloudbrainInfo, 0, setting.UI.IssuePagingNum) | ||||
| 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). | |||||
| if err := sess.Table(&Cloudbrain{}).Unscoped().Where(cond). | |||||
| Find(&cloudbrains); err != nil { | Find(&cloudbrains); err != nil { | ||||
| return nil, 0, fmt.Errorf("Find: %v", err) | return nil, 0, fmt.Errorf("Find: %v", err) | ||||
| } | } | ||||
| if opts.NeedRepoInfo { | |||||
| var ids []int64 | |||||
| for _, task := range cloudbrains { | |||||
| ids = append(ids, task.RepoID) | |||||
| } | |||||
| repositoryMap, err := GetRepositoriesMapByIDs(ids) | |||||
| if err == nil { | |||||
| for _, task := range cloudbrains { | |||||
| task.Repo = repositoryMap[task.RepoID] | |||||
| } | |||||
| } | |||||
| } | |||||
| return cloudbrains, count, nil | return cloudbrains, count, nil | ||||
| } | } | ||||
| @@ -1,7 +1,6 @@ | |||||
| package models | package models | ||||
| import ( | import ( | ||||
| "fmt" | |||||
| "strconv" | "strconv" | ||||
| "time" | "time" | ||||
| @@ -42,14 +41,14 @@ type TaskDetail struct { | |||||
| type CloudbrainDurationStatistic struct { | type CloudbrainDurationStatistic struct { | ||||
| ID int64 `xorm:"pk autoincr"` | ID int64 `xorm:"pk autoincr"` | ||||
| Cluster string | Cluster string | ||||
| AiCenterCode string | |||||
| AiCenterCode string `xorm:"INDEX"` | |||||
| AiCenterName string | AiCenterName string | ||||
| ComputeResource string | ComputeResource string | ||||
| AccCardType string | |||||
| AccCardType string `xorm:"INDEX"` | |||||
| DateTime string | |||||
| DayTime string | |||||
| HourTime int | |||||
| DateTime timeutil.TimeStamp `xorm:"INDEX"` | |||||
| DayTime string `xorm:"INDEX"` | |||||
| HourTime int `xorm:"INDEX"` | |||||
| CardsUseDuration int | CardsUseDuration int | ||||
| CardsTotalDuration int | CardsTotalDuration int | ||||
| CardsTotalNum int | CardsTotalNum int | ||||
| @@ -275,11 +274,15 @@ func GetCloudbrainByTime(beginTime int64, endTime int64) ([]*CloudbrainInfo, err | |||||
| sess := x.NewSession() | sess := x.NewSession() | ||||
| defer sess.Close() | defer sess.Close() | ||||
| var cond = builder.NewCond() | var cond = builder.NewCond() | ||||
| cond = cond.And( | |||||
| builder.And(builder.Gte{"cloudbrain.end_time": beginTime}, builder.Lte{"cloudbrain.end_time": endTime}), | |||||
| sess.Exec("if ") | |||||
| cond = cond.Or( | |||||
| builder.And(builder.Gte{"cloudbrain.end_time": beginTime}, builder.Lte{"cloudbrain.start_time": beginTime}, builder.Gt{"cloudbrain.start_time": 0}), | |||||
| ) | ) | ||||
| cond = cond.Or( | cond = cond.Or( | ||||
| builder.Eq{"cloudbrain.status": string(JobRunning)}, | |||||
| builder.And(builder.Gte{"cloudbrain.start_time": beginTime}, builder.Lte{"cloudbrain.start_time": endTime}, builder.Gt{"cloudbrain.start_time": 0}), | |||||
| ) | |||||
| cond = cond.Or( | |||||
| builder.And(builder.Eq{"cloudbrain.status": string(JobRunning)}), | |||||
| ) | ) | ||||
| sess.OrderBy("cloudbrain.created_unix ASC") | sess.OrderBy("cloudbrain.created_unix ASC") | ||||
| cloudbrains := make([]*CloudbrainInfo, 0, 10) | cloudbrains := make([]*CloudbrainInfo, 0, 10) | ||||
| @@ -309,30 +312,20 @@ func InsertCloudbrainDurationStatistic(cloudbrainDurationStatistic *CloudbrainDu | |||||
| return xStatistic.Insert(cloudbrainDurationStatistic) | 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) | |||||
| func getDurationStatistic(cb *CloudbrainDurationStatistic) (*CloudbrainDurationStatistic, error) { | |||||
| has, err := x.Get(cb) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } else if !has { | |||||
| return nil, ErrJobNotExist{} | |||||
| } | } | ||||
| if err := sess.Commit(); err != nil { | |||||
| sess.Close() | |||||
| return fmt.Errorf("Commit: %v", err) | |||||
| } | |||||
| sess.Close() | |||||
| return nil | |||||
| return cb, nil | |||||
| } | } | ||||
| func GetCanUseCardInfo() ([]*ResourceQueue, error) { | func GetCanUseCardInfo() ([]*ResourceQueue, error) { | ||||
| sess := x.NewSession() | sess := x.NewSession() | ||||
| defer sess.Close() | defer sess.Close() | ||||
| sess.OrderBy("resource_queue.id ASC") | |||||
| sess.OrderBy("resource_queue.cluster DESC, resource_queue.ai_center_code ASC") | |||||
| ResourceQueues := make([]*ResourceQueue, 0, 10) | ResourceQueues := make([]*ResourceQueue, 0, 10) | ||||
| if err := sess.Table(&ResourceQueue{}).Find(&ResourceQueues); err != nil { | if err := sess.Table(&ResourceQueue{}).Find(&ResourceQueues); err != nil { | ||||
| log.Info("find error.") | log.Info("find error.") | ||||
| @@ -346,7 +339,7 @@ func GetCardDurationStatistics(opts *DurationStatisticOptions) ([]*CloudbrainDur | |||||
| var cond = builder.NewCond() | var cond = builder.NewCond() | ||||
| if opts.BeginTime.Unix() > 0 && opts.EndTime.Unix() > 0 { | if opts.BeginTime.Unix() > 0 && opts.EndTime.Unix() > 0 { | ||||
| cond = cond.And( | 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()}), | |||||
| builder.And(builder.Gte{"cloudbrain_duration_statistic.date_time": opts.BeginTime.Unix()}, builder.Lt{"cloudbrain_duration_statistic.date_time": opts.EndTime.Unix()}), | |||||
| ) | ) | ||||
| } | } | ||||
| if opts.AiCenterCode != "" { | if opts.AiCenterCode != "" { | ||||
| @@ -365,10 +358,31 @@ func GetCardDurationStatistics(opts *DurationStatisticOptions) ([]*CloudbrainDur | |||||
| func GetDurationRecordBeginTime() ([]*CloudbrainDurationStatistic, error) { | func GetDurationRecordBeginTime() ([]*CloudbrainDurationStatistic, error) { | ||||
| sess := xStatistic.NewSession() | sess := xStatistic.NewSession() | ||||
| defer sess.Close() | defer sess.Close() | ||||
| sess.OrderBy("cloudbrain_duration_statistic.id ASC limit 1") | |||||
| sess.OrderBy("cloudbrain_duration_statistic.date_time ASC limit 1") | |||||
| CloudbrainDurationStatistics := make([]*CloudbrainDurationStatistic, 0) | CloudbrainDurationStatistics := make([]*CloudbrainDurationStatistic, 0) | ||||
| if err := sess.Table(&CloudbrainDurationStatistic{}).Find(&CloudbrainDurationStatistics); err != nil { | if err := sess.Table(&CloudbrainDurationStatistic{}).Find(&CloudbrainDurationStatistics); err != nil { | ||||
| log.Info("find error.") | log.Info("find error.") | ||||
| } | } | ||||
| return CloudbrainDurationStatistics, nil | return CloudbrainDurationStatistics, nil | ||||
| } | } | ||||
| func GetDurationRecordUpdateTime() ([]*CloudbrainDurationStatistic, error) { | |||||
| sess := xStatistic.NewSession() | |||||
| defer sess.Close() | |||||
| sess.OrderBy("cloudbrain_duration_statistic.date_time DESC limit 1") | |||||
| CloudbrainDurationStatistics := make([]*CloudbrainDurationStatistic, 0) | |||||
| if err := sess.Table(&CloudbrainDurationStatistic{}).Find(&CloudbrainDurationStatistics); err != nil { | |||||
| log.Info("find error.") | |||||
| } | |||||
| return CloudbrainDurationStatistics, nil | |||||
| } | |||||
| func DeleteCloudbrainDurationStatistic(beginTime timeutil.TimeStamp, endTime timeutil.TimeStamp) error { | |||||
| sess := xStatistic.NewSession() | |||||
| defer sess.Close() | |||||
| if _, err := sess.Exec("DELETE FROM cloudbrain_duration_statistic WHERE cloudbrain_duration_statistic.date_time BETWEEN ? AND ?", beginTime, endTime); err != nil { | |||||
| log.Info("DELETE cloudbrain_duration_statistic data error.") | |||||
| return err | |||||
| } | |||||
| return nil | |||||
| } | |||||
| @@ -28,6 +28,23 @@ type FileChunk struct { | |||||
| UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | ||||
| } | } | ||||
| type ModelFileChunk struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| UUID string `xorm:"INDEX"` | |||||
| Md5 string `xorm:"INDEX"` | |||||
| ModelUUID string `xorm:"INDEX"` | |||||
| ObjectName string `xorm:"DEFAULT ''"` | |||||
| IsUploaded int `xorm:"DEFAULT 0"` // not uploaded: 0, uploaded: 1 | |||||
| UploadID string `xorm:"UNIQUE"` //minio upload id | |||||
| TotalChunks int | |||||
| Size int64 | |||||
| UserID int64 `xorm:"INDEX"` | |||||
| Type int `xorm:"INDEX DEFAULT 0"` | |||||
| CompletedParts []string `xorm:"DEFAULT ''"` // chunkNumber+etag eg: ,1-asqwewqe21312312.2-123hjkas | |||||
| CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
| UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
| } | |||||
| // GetFileChunkByMD5 returns fileChunk by given id | // GetFileChunkByMD5 returns fileChunk by given id | ||||
| func GetFileChunkByMD5(md5 string) (*FileChunk, error) { | func GetFileChunkByMD5(md5 string) (*FileChunk, error) { | ||||
| return getFileChunkByMD5(x, md5) | return getFileChunkByMD5(x, md5) | ||||
| @@ -49,6 +66,21 @@ func GetFileChunkByMD5AndUser(md5 string, userID int64, typeCloudBrain int) (*Fi | |||||
| return getFileChunkByMD5AndUser(x, md5, userID, typeCloudBrain) | return getFileChunkByMD5AndUser(x, md5, userID, typeCloudBrain) | ||||
| } | } | ||||
| func GetModelFileChunkByMD5AndUser(md5 string, userID int64, typeCloudBrain int, uuid string) (*ModelFileChunk, error) { | |||||
| return getModelFileChunkByMD5AndUser(x, md5, userID, typeCloudBrain, uuid) | |||||
| } | |||||
| func getModelFileChunkByMD5AndUser(e Engine, md5 string, userID int64, typeCloudBrain int, uuid string) (*ModelFileChunk, error) { | |||||
| fileChunk := new(ModelFileChunk) | |||||
| if has, err := e.Where("md5 = ? and user_id = ? and type = ? and model_uuid= ?", md5, userID, typeCloudBrain, uuid).Get(fileChunk); err != nil { | |||||
| return nil, err | |||||
| } else if !has { | |||||
| return nil, ErrFileChunkNotExist{md5, ""} | |||||
| } | |||||
| return fileChunk, nil | |||||
| } | |||||
| func getFileChunkByMD5AndUser(e Engine, md5 string, userID int64, typeCloudBrain int) (*FileChunk, error) { | func getFileChunkByMD5AndUser(e Engine, md5 string, userID int64, typeCloudBrain int) (*FileChunk, error) { | ||||
| fileChunk := new(FileChunk) | fileChunk := new(FileChunk) | ||||
| @@ -76,6 +108,21 @@ func getFileChunkByUUID(e Engine, uuid string) (*FileChunk, error) { | |||||
| return fileChunk, nil | return fileChunk, nil | ||||
| } | } | ||||
| func GetModelFileChunkByUUID(uuid string) (*ModelFileChunk, error) { | |||||
| return getModelFileChunkByUUID(x, uuid) | |||||
| } | |||||
| func getModelFileChunkByUUID(e Engine, uuid string) (*ModelFileChunk, error) { | |||||
| fileChunk := new(ModelFileChunk) | |||||
| if has, err := e.Where("uuid = ?", uuid).Get(fileChunk); err != nil { | |||||
| return nil, err | |||||
| } else if !has { | |||||
| return nil, ErrFileChunkNotExist{"", uuid} | |||||
| } | |||||
| return fileChunk, nil | |||||
| } | |||||
| // InsertFileChunk insert a record into file_chunk. | // InsertFileChunk insert a record into file_chunk. | ||||
| func InsertFileChunk(fileChunk *FileChunk) (_ *FileChunk, err error) { | func InsertFileChunk(fileChunk *FileChunk) (_ *FileChunk, err error) { | ||||
| if _, err := x.Insert(fileChunk); err != nil { | if _, err := x.Insert(fileChunk); err != nil { | ||||
| @@ -85,6 +132,14 @@ func InsertFileChunk(fileChunk *FileChunk) (_ *FileChunk, err error) { | |||||
| return fileChunk, nil | return fileChunk, nil | ||||
| } | } | ||||
| // InsertFileChunk insert a record into file_chunk. | |||||
| func InsertModelFileChunk(fileChunk *ModelFileChunk) (_ *ModelFileChunk, err error) { | |||||
| if _, err := x.Insert(fileChunk); err != nil { | |||||
| return nil, err | |||||
| } | |||||
| return fileChunk, nil | |||||
| } | |||||
| func DeleteFileChunkById(uuid string) (*FileChunk, error) { | func DeleteFileChunkById(uuid string) (*FileChunk, error) { | ||||
| return deleteFileChunkById(x, uuid) | return deleteFileChunkById(x, uuid) | ||||
| } | } | ||||
| @@ -106,6 +161,17 @@ func deleteFileChunkById(e Engine, uuid string) (*FileChunk, error) { | |||||
| } | } | ||||
| } | } | ||||
| func UpdateModelFileChunk(fileChunk *ModelFileChunk) error { | |||||
| return updateModelFileChunk(x, fileChunk) | |||||
| } | |||||
| func updateModelFileChunk(e Engine, fileChunk *ModelFileChunk) error { | |||||
| var sess *xorm.Session | |||||
| sess = e.Where("uuid = ?", fileChunk.UUID) | |||||
| _, err := sess.Cols("is_uploaded").Update(fileChunk) | |||||
| return err | |||||
| } | |||||
| // UpdateFileChunk updates the given file_chunk in database | // UpdateFileChunk updates the given file_chunk in database | ||||
| func UpdateFileChunk(fileChunk *FileChunk) error { | func UpdateFileChunk(fileChunk *FileChunk) error { | ||||
| return updateFileChunk(x, fileChunk) | return updateFileChunk(x, fileChunk) | ||||
| @@ -127,3 +193,12 @@ func deleteFileChunk(e Engine, fileChunk *FileChunk) error { | |||||
| _, err := e.ID(fileChunk.ID).Delete(fileChunk) | _, err := e.ID(fileChunk.ID).Delete(fileChunk) | ||||
| return err | return err | ||||
| } | } | ||||
| func DeleteModelFileChunk(fileChunk *ModelFileChunk) error { | |||||
| return deleteModelFileChunk(x, fileChunk) | |||||
| } | |||||
| func deleteModelFileChunk(e Engine, fileChunk *ModelFileChunk) error { | |||||
| _, err := e.ID(fileChunk.ID).Delete(fileChunk) | |||||
| return err | |||||
| } | |||||
| @@ -136,6 +136,7 @@ func init() { | |||||
| new(ImageTopic), | new(ImageTopic), | ||||
| new(ImageTopicRelation), | new(ImageTopicRelation), | ||||
| new(FileChunk), | new(FileChunk), | ||||
| new(ModelFileChunk), | |||||
| new(BlockChain), | new(BlockChain), | ||||
| new(RecommendOrg), | new(RecommendOrg), | ||||
| new(AiModelManage), | new(AiModelManage), | ||||
| @@ -185,6 +186,7 @@ func init() { | |||||
| new(UserAnalysisPara), | new(UserAnalysisPara), | ||||
| new(Invitation), | new(Invitation), | ||||
| new(CloudbrainDurationStatistic), | new(CloudbrainDurationStatistic), | ||||
| new(UserSummaryCurrentYear), | |||||
| ) | ) | ||||
| gonicNames := []string{"SSL", "UID"} | gonicNames := []string{"SSL", "UID"} | ||||
| @@ -143,6 +143,9 @@ func InsertResourceQueue(queue ResourceQueue) (int64, error) { | |||||
| func UpdateResourceQueueById(queueId int64, queue ResourceQueue) (int64, error) { | func UpdateResourceQueueById(queueId int64, queue ResourceQueue) (int64, error) { | ||||
| return x.ID(queueId).Update(&queue) | return x.ID(queueId).Update(&queue) | ||||
| } | } | ||||
| func UpdateResourceCardsTotalNum(queueId int64, queue ResourceQueue) (int64, error) { | |||||
| return x.ID(queueId).Cols("cards_total_num", "remark").Update(&queue) | |||||
| } | |||||
| func SearchResourceQueue(opts SearchResourceQueueOptions) (int64, []ResourceQueue, error) { | func SearchResourceQueue(opts SearchResourceQueueOptions) (int64, []ResourceQueue, error) { | ||||
| var cond = builder.NewCond() | var cond = builder.NewCond() | ||||
| @@ -313,9 +316,6 @@ func SyncGrampusQueues(updateList []ResourceQueue, insertList []ResourceQueue, e | |||||
| if _, err = sess.In("id", deleteSpcIds).Update(&ResourceSpecification{Status: SpecOffShelf}); err != nil { | if _, err = sess.In("id", deleteSpcIds).Update(&ResourceSpecification{Status: SpecOffShelf}); err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| if _, err = sess.In("spec_id", deleteSpcIds).Delete(&ResourceSceneSpec{}); err != nil { | |||||
| return err | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -116,7 +116,7 @@ func InsertResourceScene(r ResourceSceneReq) error { | |||||
| //check | //check | ||||
| specs := make([]ResourceSpecification, 0) | specs := make([]ResourceSpecification, 0) | ||||
| cond := builder.In("id", r.SpecIds).And(builder.Eq{"status": SpecOnShelf}) | |||||
| cond := builder.In("id", r.SpecIds) | |||||
| if err := sess.Where(cond).Find(&specs); err != nil { | if err := sess.Where(cond).Find(&specs); err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -175,7 +175,7 @@ func UpdateResourceScene(r ResourceSceneReq) error { | |||||
| } | } | ||||
| //check specification | //check specification | ||||
| specs := make([]ResourceSpecification, 0) | specs := make([]ResourceSpecification, 0) | ||||
| cond := builder.In("id", r.SpecIds).And(builder.Eq{"status": SpecOnShelf}) | |||||
| cond := builder.In("id", r.SpecIds) | |||||
| if err := sess.Where(cond).Find(&specs); err != nil { | if err := sess.Where(cond).Find(&specs); err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -12,6 +12,13 @@ const ( | |||||
| SpecOffShelf | SpecOffShelf | ||||
| ) | ) | ||||
| type SearchSpecOrderBy int | |||||
| const ( | |||||
| SearchSpecOrderById SearchSpecOrderBy = iota | |||||
| SearchSpecOrder4Standard | |||||
| ) | |||||
| type ResourceSpecification struct { | type ResourceSpecification struct { | ||||
| ID int64 `xorm:"pk autoincr"` | ID int64 `xorm:"pk autoincr"` | ||||
| QueueId int64 `xorm:"INDEX"` | QueueId int64 `xorm:"INDEX"` | ||||
| @@ -85,6 +92,7 @@ type SearchResourceSpecificationOptions struct { | |||||
| Status int | Status int | ||||
| Cluster string | Cluster string | ||||
| AvailableCode int | AvailableCode int | ||||
| OrderBy SearchSpecOrderBy | |||||
| } | } | ||||
| type SearchResourceBriefSpecificationOptions struct { | type SearchResourceBriefSpecificationOptions struct { | ||||
| @@ -168,6 +176,7 @@ type FindSpecsOptions struct { | |||||
| UseShareMemGiB bool | UseShareMemGiB bool | ||||
| //if true,find specs no matter used or not used in scene. if false,only find specs used in scene | //if true,find specs no matter used or not used in scene. if false,only find specs used in scene | ||||
| RequestAll bool | RequestAll bool | ||||
| SpecStatus int | |||||
| } | } | ||||
| type Specification struct { | type Specification struct { | ||||
| @@ -232,10 +241,18 @@ func SearchResourceSpecification(opts SearchResourceSpecificationOptions) (int64 | |||||
| return 0, nil, err | return 0, nil, err | ||||
| } | } | ||||
| var orderby = "" | |||||
| switch opts.OrderBy { | |||||
| case SearchSpecOrder4Standard: | |||||
| orderby = "resource_queue.compute_resource asc,resource_queue.acc_card_type asc,resource_specification.acc_cards_num asc,resource_specification.cpu_cores asc,resource_specification.mem_gi_b asc,resource_specification.share_mem_gi_b asc" | |||||
| default: | |||||
| orderby = "resource_specification.id desc" | |||||
| } | |||||
| r := make([]ResourceSpecAndQueue, 0) | r := make([]ResourceSpecAndQueue, 0) | ||||
| err = x.Where(cond). | err = x.Where(cond). | ||||
| Join("INNER", "resource_queue", "resource_queue.ID = resource_specification.queue_id"). | Join("INNER", "resource_queue", "resource_queue.ID = resource_specification.queue_id"). | ||||
| Desc("resource_specification.id"). | |||||
| OrderBy(orderby). | |||||
| Limit(opts.PageSize, (opts.Page-1)*opts.PageSize). | Limit(opts.PageSize, (opts.Page-1)*opts.PageSize). | ||||
| Unscoped().Find(&r) | Unscoped().Find(&r) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -269,10 +286,6 @@ func ResourceSpecOffShelf(id int64) (int64, error) { | |||||
| } | } | ||||
| sess.Close() | sess.Close() | ||||
| }() | }() | ||||
| //delete scene spec relation | |||||
| if _, err = sess.Where("spec_id = ?", id).Delete(&ResourceSceneSpec{}); err != nil { | |||||
| return 0, err | |||||
| } | |||||
| param := ResourceSpecification{ | param := ResourceSpecification{ | ||||
| Status: SpecOffShelf, | Status: SpecOffShelf, | ||||
| @@ -326,9 +339,6 @@ func SyncGrampusSpecs(updateList []ResourceSpecification, insertList []ResourceS | |||||
| if _, err = sess.Cols("status", "is_available").In("id", deleteIds).Update(&ResourceSpecification{Status: SpecOffShelf, IsAvailable: false}); err != nil { | if _, err = sess.Cols("status", "is_available").In("id", deleteIds).Update(&ResourceSpecification{Status: SpecOffShelf, IsAvailable: false}); err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| if _, err = sess.In("spec_id", deleteIds).Delete(&ResourceSceneSpec{}); err != nil { | |||||
| return err | |||||
| } | |||||
| } | } | ||||
| //update exists specs | //update exists specs | ||||
| @@ -393,6 +403,9 @@ func FindSpecs(opts FindSpecsOptions) ([]*Specification, error) { | |||||
| if opts.UseShareMemGiB { | if opts.UseShareMemGiB { | ||||
| cond = cond.And(builder.Eq{"resource_specification.share_mem_gi_b": opts.ShareMemGiB}) | cond = cond.And(builder.Eq{"resource_specification.share_mem_gi_b": opts.ShareMemGiB}) | ||||
| } | } | ||||
| if opts.SpecStatus > 0 { | |||||
| cond = cond.And(builder.Eq{"resource_specification.status": opts.SpecStatus}) | |||||
| } | |||||
| r := make([]*Specification, 0) | r := make([]*Specification, 0) | ||||
| s := x.Where(cond). | s := x.Where(cond). | ||||
| Join("INNER", "resource_queue", "resource_queue.id = resource_specification.queue_id") | Join("INNER", "resource_queue", "resource_queue.id = resource_specification.queue_id") | ||||
| @@ -3,12 +3,15 @@ package models | |||||
| import ( | import ( | ||||
| "encoding/json" | "encoding/json" | ||||
| "fmt" | "fmt" | ||||
| "io/ioutil" | |||||
| "net/http" | |||||
| "sort" | "sort" | ||||
| "strconv" | "strconv" | ||||
| "strings" | "strings" | ||||
| "time" | "time" | ||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| "code.gitea.io/gitea/modules/setting" | |||||
| "code.gitea.io/gitea/modules/timeutil" | "code.gitea.io/gitea/modules/timeutil" | ||||
| "xorm.io/builder" | "xorm.io/builder" | ||||
| "xorm.io/xorm" | "xorm.io/xorm" | ||||
| @@ -19,185 +22,6 @@ const ( | |||||
| BATCH_INSERT_SIZE = 50 | BATCH_INSERT_SIZE = 50 | ||||
| ) | ) | ||||
| type UserBusinessAnalysisAll struct { | |||||
| ID int64 `xorm:"pk"` | |||||
| CountDate int64 `xorm:"pk"` | |||||
| //action :ActionMergePullRequest // 11 | |||||
| CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //action :ActionCommitRepo // 5 | |||||
| CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //action :ActionCreateIssue // 10 | |||||
| IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //comment table current date | |||||
| CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //watch table current date | |||||
| FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //star table current date | |||||
| StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //follow table | |||||
| WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| // user table | |||||
| GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||||
| // | |||||
| CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //attachement table | |||||
| CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //0 | |||||
| CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //issue, issueassignees | |||||
| SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //baike | |||||
| EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //user | |||||
| RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
| //repo | |||||
| CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //login count, from elk | |||||
| LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //openi index | |||||
| OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| //user | |||||
| Email string `xorm:"NOT NULL"` | |||||
| //user | |||||
| Name string `xorm:"NOT NULL"` | |||||
| DataDate string `xorm:"NULL"` | |||||
| //cloudbraintask | |||||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserIndexPrimitive float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserLocation string `xorm:"NULL"` | |||||
| FocusOtherUser int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectedDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| RecommendDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectedImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| RecommendImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| Phone string `xorm:"NULL"` | |||||
| InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| } | |||||
| type UserBusinessAnalysis struct { | |||||
| ID int64 `xorm:"pk"` | |||||
| DataDate string `xorm:"pk"` | |||||
| CountDate int64 `xorm:"NULL"` | |||||
| //action :ActionMergePullRequest // 11 | |||||
| CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //action :ActionCommitRepo // 5 | |||||
| CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //action :ActionCreateIssue // 6 | |||||
| IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //comment table current date | |||||
| CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //watch table current date | |||||
| FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //star table current date | |||||
| StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //follow table | |||||
| WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| // user table | |||||
| GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||||
| // | |||||
| CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //attachement table | |||||
| CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //0 | |||||
| CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //issue, issueassignees | |||||
| SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //baike | |||||
| EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //user | |||||
| RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
| //repo | |||||
| CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //login count, from elk | |||||
| LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //openi index | |||||
| OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| //user | |||||
| Email string `xorm:"NOT NULL"` | |||||
| //user | |||||
| Name string `xorm:"NOT NULL"` | |||||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserIndexPrimitive float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserLocation string `xorm:"NULL"` | |||||
| FocusOtherUser int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectedDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| RecommendDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectedImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| RecommendImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| Phone string `xorm:"NULL"` | |||||
| InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| } | |||||
| type UserBusinessAnalysisQueryOptions struct { | type UserBusinessAnalysisQueryOptions struct { | ||||
| ListOptions | ListOptions | ||||
| UserName string | UserName string | ||||
| @@ -499,7 +323,7 @@ func QueryUserStaticDataForUserDefine(opts *UserBusinessAnalysisQueryOptions, wi | |||||
| DataDate := currentTimeNow.Format("2006-01-02 15:04") | DataDate := currentTimeNow.Format("2006-01-02 15:04") | ||||
| CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | ||||
| CommitCountMap := queryCommitAction(start_unix, end_unix, 5) | |||||
| CommitCountMap, _ := queryCommitAction(start_unix, end_unix, 5) | |||||
| IssueCountMap := queryCreateIssue(start_unix, end_unix) | IssueCountMap := queryCreateIssue(start_unix, end_unix) | ||||
| CommentCountMap := queryComment(start_unix, end_unix) | CommentCountMap := queryComment(start_unix, end_unix) | ||||
| @@ -517,16 +341,16 @@ func QueryUserStaticDataForUserDefine(opts *UserBusinessAnalysisQueryOptions, wi | |||||
| CommitCodeSizeMapJson, _ := json.Marshal(CommitCodeSizeMap) | CommitCodeSizeMapJson, _ := json.Marshal(CommitCodeSizeMap) | ||||
| log.Info("CommitCodeSizeMapJson=" + string(CommitCodeSizeMapJson)) | log.Info("CommitCodeSizeMapJson=" + string(CommitCodeSizeMapJson)) | ||||
| } | } | ||||
| CommitDatasetSizeMap, CommitDatasetNumMap := queryDatasetSize(start_unix, end_unix) | |||||
| CommitDatasetSizeMap, CommitDatasetNumMap, _ := queryDatasetSize(start_unix, end_unix) | |||||
| SolveIssueCountMap := querySolveIssue(start_unix, end_unix) | SolveIssueCountMap := querySolveIssue(start_unix, end_unix) | ||||
| CreateRepoCountMap := queryUserCreateRepo(start_unix, end_unix) | |||||
| CreateRepoCountMap, _, _ := queryUserCreateRepo(start_unix, end_unix) | |||||
| LoginCountMap := queryLoginCount(start_unix, end_unix) | LoginCountMap := queryLoginCount(start_unix, end_unix) | ||||
| OpenIIndexMap := queryUserRepoOpenIIndex(start_unix, end_unix) | OpenIIndexMap := queryUserRepoOpenIIndex(start_unix, end_unix) | ||||
| CloudBrainTaskMap, CloudBrainTaskItemMap := queryCloudBrainTask(start_unix, end_unix) | CloudBrainTaskMap, CloudBrainTaskItemMap := queryCloudBrainTask(start_unix, end_unix) | ||||
| AiModelManageMap := queryUserModel(start_unix, end_unix) | AiModelManageMap := queryUserModel(start_unix, end_unix) | ||||
| CollectDataset, CollectedDataset := queryDatasetStars(start_unix, end_unix) | CollectDataset, CollectedDataset := queryDatasetStars(start_unix, end_unix) | ||||
| RecommendDataset := queryRecommedDataSet(start_unix, end_unix) | |||||
| RecommendDataset, _ := queryRecommedDataSet(start_unix, end_unix) | |||||
| CollectImage, CollectedImage := queryImageStars(start_unix, end_unix) | CollectImage, CollectedImage := queryImageStars(start_unix, end_unix) | ||||
| RecommendImage := queryRecommedImage(start_unix, end_unix) | RecommendImage := queryRecommedImage(start_unix, end_unix) | ||||
| @@ -752,7 +576,7 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS | |||||
| startTime := currentTimeNow.AddDate(0, 0, -1) | startTime := currentTimeNow.AddDate(0, 0, -1) | ||||
| CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | ||||
| CommitCountMap := queryCommitAction(start_unix, end_unix, 5) | |||||
| CommitCountMap, mostActiveMap := queryCommitAction(start_unix, end_unix, 5) | |||||
| IssueCountMap := queryCreateIssue(start_unix, end_unix) | IssueCountMap := queryCreateIssue(start_unix, end_unix) | ||||
| CommentCountMap := queryComment(start_unix, end_unix) | CommentCountMap := queryComment(start_unix, end_unix) | ||||
| @@ -764,13 +588,13 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS | |||||
| log.Info("query commit code errr.") | log.Info("query commit code errr.") | ||||
| } else { | } else { | ||||
| log.Info("query commit code size, len=" + fmt.Sprint(len(CommitCodeSizeMap))) | log.Info("query commit code size, len=" + fmt.Sprint(len(CommitCodeSizeMap))) | ||||
| CommitCodeSizeMapJson, _ := json.Marshal(CommitCodeSizeMap) | |||||
| log.Info("CommitCodeSizeMapJson=" + string(CommitCodeSizeMapJson)) | |||||
| //CommitCodeSizeMapJson, _ := json.Marshal(CommitCodeSizeMap) | |||||
| //log.Info("CommitCodeSizeMapJson=" + string(CommitCodeSizeMapJson)) | |||||
| } | } | ||||
| //CommitCodeSizeMap := queryCommitCodeSize(StartTimeNextDay.Unix(), EndTimeNextDay.Unix()) | //CommitCodeSizeMap := queryCommitCodeSize(StartTimeNextDay.Unix(), EndTimeNextDay.Unix()) | ||||
| CommitDatasetSizeMap, CommitDatasetNumMap := queryDatasetSize(start_unix, end_unix) | |||||
| CommitDatasetSizeMap, CommitDatasetNumMap, dataSetDownloadMap := queryDatasetSize(start_unix, end_unix) | |||||
| SolveIssueCountMap := querySolveIssue(start_unix, end_unix) | SolveIssueCountMap := querySolveIssue(start_unix, end_unix) | ||||
| CreateRepoCountMap := queryUserCreateRepo(start_unix, end_unix) | |||||
| CreateRepoCountMap, DetailInfoMap, MostDownloadMap := queryUserCreateRepo(start_unix, end_unix) | |||||
| LoginCountMap := queryLoginCount(start_unix, end_unix) | LoginCountMap := queryLoginCount(start_unix, end_unix) | ||||
| OpenIIndexMap := queryUserRepoOpenIIndex(startTime.Unix(), end_unix) | OpenIIndexMap := queryUserRepoOpenIIndex(startTime.Unix(), end_unix) | ||||
| @@ -778,14 +602,19 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS | |||||
| AiModelManageMap := queryUserModel(start_unix, end_unix) | AiModelManageMap := queryUserModel(start_unix, end_unix) | ||||
| CollectDataset, CollectedDataset := queryDatasetStars(start_unix, end_unix) | CollectDataset, CollectedDataset := queryDatasetStars(start_unix, end_unix) | ||||
| RecommendDataset := queryRecommedDataSet(start_unix, end_unix) | |||||
| RecommendDataset, CreatedDataset := queryRecommedDataSet(start_unix, end_unix) | |||||
| CollectImage, CollectedImage := queryImageStars(start_unix, end_unix) | CollectImage, CollectedImage := queryImageStars(start_unix, end_unix) | ||||
| RecommendImage := queryRecommedImage(start_unix, end_unix) | RecommendImage := queryRecommedImage(start_unix, end_unix) | ||||
| InvitationMap := queryUserInvitationCount(start_unix, end_unix) | InvitationMap := queryUserInvitationCount(start_unix, end_unix) | ||||
| DataDate := currentTimeNow.Format("2006-01-02") + " 00:01" | DataDate := currentTimeNow.Format("2006-01-02") + " 00:01" | ||||
| bonusMap := make(map[string]map[string]int) | |||||
| if tableName == "user_business_analysis_current_year" { | |||||
| bonusMap = getBonusMap() | |||||
| log.Info("truncate all data from table:user_summary_current_year ") | |||||
| statictisSess.Exec("TRUNCATE TABLE user_summary_current_year") | |||||
| } | |||||
| cond := "type != 1 and is_active=true" | cond := "type != 1 and is_active=true" | ||||
| count, err := sess.Where(cond).Count(new(User)) | count, err := sess.Where(cond).Count(new(User)) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -883,6 +712,37 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS | |||||
| userMetrics["TotalHasActivityUser"] = getMapKeyStringValue("TotalHasActivityUser", userMetrics) + 1 | userMetrics["TotalHasActivityUser"] = getMapKeyStringValue("TotalHasActivityUser", userMetrics) + 1 | ||||
| } | } | ||||
| } | } | ||||
| if tableName == "user_business_analysis_current_year" { | |||||
| //年度数据 | |||||
| subTime := time.Now().UTC().Sub(dateRecordAll.RegistDate.AsTime().UTC()) | |||||
| mostActiveDay := "" | |||||
| if userInfo, ok := mostActiveMap[dateRecordAll.ID]; ok { | |||||
| mostActiveDay = getMostActiveJson(userInfo) | |||||
| } | |||||
| scoreMap := make(map[string]float64) | |||||
| repoInfo := getRepoDetailInfo(DetailInfoMap, dateRecordAll.ID, MostDownloadMap) | |||||
| dataSetInfo, datasetscore := getDataSetInfo(dateRecordAll.ID, CreatedDataset, dataSetDownloadMap, CommitDatasetNumMap, CollectedDataset) | |||||
| scoreMap["datasetscore"] = datasetscore | |||||
| codeInfo, codescore := getCodeInfo(dateRecordAll) | |||||
| scoreMap["codescore"] = codescore | |||||
| cloudBrainInfo := getCloudBrainInfo(dateRecordAll, CloudBrainTaskItemMap, scoreMap) | |||||
| playARoll := getPlayARoll(bonusMap, dateRecordAll.Name, scoreMap) | |||||
| re := &UserSummaryCurrentYear{ | |||||
| ID: dateRecordAll.ID, | |||||
| Name: dateRecordAll.Name, | |||||
| Email: dateRecordAll.Email, | |||||
| Phone: dateRecordAll.Phone, | |||||
| RegistDate: dateRecordAll.RegistDate, | |||||
| DateCount: int(subTime.Hours()) / 24, | |||||
| MostActiveDay: mostActiveDay, | |||||
| RepoInfo: repoInfo, | |||||
| DataSetInfo: dataSetInfo, | |||||
| CodeInfo: codeInfo, | |||||
| CloudBrainInfo: cloudBrainInfo, | |||||
| PlayARoll: playARoll, | |||||
| } | |||||
| statictisSess.Insert(re) | |||||
| } | |||||
| } | } | ||||
| if len(dateRecordBatch) > 0 { | if len(dateRecordBatch) > 0 { | ||||
| err := insertTable(dateRecordBatch, tableName, statictisSess) | err := insertTable(dateRecordBatch, tableName, statictisSess) | ||||
| @@ -890,6 +750,7 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS | |||||
| if err != nil { | if err != nil { | ||||
| log.Info("insert all data failed." + err.Error()) | log.Info("insert all data failed." + err.Error()) | ||||
| } | } | ||||
| } | } | ||||
| indexTotal += PAGE_SIZE | indexTotal += PAGE_SIZE | ||||
| if indexTotal >= count { | if indexTotal >= count { | ||||
| @@ -911,6 +772,204 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS | |||||
| log.Info("refresh data finished.tableName=" + tableName + " total record:" + fmt.Sprint(insertCount)) | log.Info("refresh data finished.tableName=" + tableName + " total record:" + fmt.Sprint(insertCount)) | ||||
| } | } | ||||
| func getBonusMap() map[string]map[string]int { | |||||
| bonusMap := make(map[string]map[string]int) | |||||
| url := setting.RecommentRepoAddr + "bonus/record.txt" | |||||
| content, err := GetContentFromPromote(url) | |||||
| if err == nil { | |||||
| filenames := strings.Split(content, "\n") | |||||
| for i := 0; i < len(filenames); i++ { | |||||
| url = setting.RecommentRepoAddr + "bonus/" + filenames[i] | |||||
| csvContent, err1 := GetContentFromPromote(url) | |||||
| if err1 == nil { | |||||
| //read csv | |||||
| lines := strings.Split(csvContent, "\n") | |||||
| for j := 1; j < len(lines); j++ { | |||||
| aLine := strings.Split(lines[j], ",") | |||||
| if len(aLine) < 7 { | |||||
| continue | |||||
| } | |||||
| userName := aLine[1] | |||||
| //email := lines[2] | |||||
| record, ok := bonusMap[userName] | |||||
| if !ok { | |||||
| record = make(map[string]int) | |||||
| } | |||||
| record["times"] = getMapKeyStringValue("times", record) + getIntValue(aLine[3]) | |||||
| record["total_bonus"] = getMapKeyStringValue("total_bonus", record) + getIntValue(aLine[4]) | |||||
| record["total_cardtime"] = getMapKeyStringValue("total_cardtime", record) + getIntValue(aLine[5]) | |||||
| record["total_giveup"] = getMapKeyStringValue("total_giveup", record) + getIntValue(aLine[6]) | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return bonusMap | |||||
| } | |||||
| func getIntValue(val string) int { | |||||
| i, err := strconv.Atoi(val) | |||||
| if err == nil { | |||||
| return i | |||||
| } | |||||
| return 0 | |||||
| } | |||||
| func getPlayARoll(bonusMap map[string]map[string]int, userName string, scoreMap map[string]float64) string { | |||||
| bonusInfo := make(map[string]string) | |||||
| record, ok := bonusMap[userName] | |||||
| if ok { | |||||
| rollscore := 0.0 | |||||
| bonusInfo["times"] = fmt.Sprint(record["times"]) | |||||
| if record["times"] >= 4 { | |||||
| rollscore = float64(record["times"]) / float64(4) | |||||
| } | |||||
| scoreMap["rollscore"] = rollscore | |||||
| bonusInfo["total_bonus"] = fmt.Sprint(record["total_bonus"]) | |||||
| bonusInfo["total_cardtime"] = fmt.Sprint(record["total_cardtime"]) | |||||
| bonusInfo["total_giveup"] = fmt.Sprint(record["total_giveup"]) | |||||
| bonusInfoJson, _ := json.Marshal(bonusInfo) | |||||
| return string(bonusInfoJson) | |||||
| } else { | |||||
| return "" | |||||
| } | |||||
| } | |||||
| func getCloudBrainInfo(dateRecordAll UserBusinessAnalysisAll, CloudBrainTaskItemMap map[string]int, scoreMap map[string]float64) string { | |||||
| trainscore := 0.0 | |||||
| debugscore := 0.0 | |||||
| runtime := 0.0 | |||||
| if dateRecordAll.CloudBrainTaskNum > 0 { | |||||
| cloudBrainInfo := make(map[string]string) | |||||
| cloudBrainInfo["create_task_num"] = fmt.Sprint(dateRecordAll.CloudBrainTaskNum) | |||||
| cloudBrainInfo["debug_task_num"] = fmt.Sprint(dateRecordAll.GpuDebugJob + dateRecordAll.NpuDebugJob) | |||||
| if dateRecordAll.GpuDebugJob+dateRecordAll.NpuDebugJob >= 50 { | |||||
| debugscore = float64(dateRecordAll.GpuDebugJob+dateRecordAll.NpuDebugJob) / float64(50) | |||||
| } | |||||
| cloudBrainInfo["train_task_num"] = fmt.Sprint(dateRecordAll.GpuTrainJob + dateRecordAll.NpuTrainJob) | |||||
| if dateRecordAll.GpuTrainJob+dateRecordAll.NpuTrainJob >= 50 { | |||||
| trainscore = float64(dateRecordAll.GpuTrainJob+dateRecordAll.NpuTrainJob) / float64(50) | |||||
| } | |||||
| cloudBrainInfo["inference_task_num"] = fmt.Sprint(dateRecordAll.NpuInferenceJob + CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_GpuInferenceJob"]) | |||||
| cloudBrainInfo["card_runtime"] = fmt.Sprint(dateRecordAll.CloudBrainRunTime) | |||||
| if dateRecordAll.CloudBrainRunTime >= 100 { | |||||
| runtime = float64(dateRecordAll.CloudBrainRunTime) / float64(100) | |||||
| } | |||||
| cloudBrainInfo["card_runtime_money"] = fmt.Sprint(dateRecordAll.CloudBrainRunTime * 5) | |||||
| cloudBrainInfo["CloudBrainOne"] = fmt.Sprint(CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_CloudBrainOne"]) | |||||
| cloudBrainInfo["CloudBrainTwo"] = fmt.Sprint(CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_CloudBrainTwo"]) | |||||
| cloudBrainInfo["C2Net"] = fmt.Sprint(CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_C2Net"]) | |||||
| cloudBrainInfoJson, _ := json.Marshal(cloudBrainInfo) | |||||
| scoreMap["trainscore"] = trainscore | |||||
| scoreMap["debugscore"] = debugscore | |||||
| scoreMap["runtime"] = runtime | |||||
| return string(cloudBrainInfoJson) | |||||
| } else { | |||||
| scoreMap["trainscore"] = trainscore | |||||
| scoreMap["debugscore"] = debugscore | |||||
| scoreMap["runtime"] = runtime | |||||
| return "" | |||||
| } | |||||
| } | |||||
| func getCodeInfo(dateRecordAll UserBusinessAnalysisAll) (string, float64) { | |||||
| if dateRecordAll.CommitCount > 0 { | |||||
| codeInfo := make(map[string]string) | |||||
| codeInfo["commit_count"] = fmt.Sprint(dateRecordAll.CommitCount) | |||||
| codeInfo["commit_line"] = fmt.Sprint(dateRecordAll.CommitCodeSize) | |||||
| score := 0.0 | |||||
| score = float64(dateRecordAll.CommitCodeSize) / float64(dateRecordAll.CommitCount) / float64(20000) | |||||
| if score < (float64(dateRecordAll.CommitCount) / float64(100)) { | |||||
| score = float64(dateRecordAll.CommitCount) / float64(100) | |||||
| } | |||||
| codeInfo["score"] = fmt.Sprintf("%.2f", score) | |||||
| codeInfoJson, _ := json.Marshal(codeInfo) | |||||
| return string(codeInfoJson), score | |||||
| } else { | |||||
| return "", 0 | |||||
| } | |||||
| } | |||||
| func getDataSetInfo(userId int64, CreatedDataset map[int64]int, dataSetDownloadMap map[int64]int, CommitDatasetNumMap map[int64]int, CollectedDataset map[int64]int) (string, float64) { | |||||
| datasetInfo := make(map[string]string) | |||||
| score := 0.0 | |||||
| if create_count, ok := CreatedDataset[userId]; ok { | |||||
| datasetInfo["create_count"] = fmt.Sprint(create_count) | |||||
| score = float64(create_count) / 10 | |||||
| } | |||||
| if upload_count, ok := CommitDatasetNumMap[userId]; ok { | |||||
| datasetInfo["upload_file_count"] = fmt.Sprint(upload_count) | |||||
| } | |||||
| if download_count, ok := dataSetDownloadMap[userId]; ok { | |||||
| datasetInfo["download_count"] = fmt.Sprint(download_count) | |||||
| } | |||||
| if cllected_count, ok := CollectedDataset[userId]; ok { | |||||
| datasetInfo["cllected_count"] = fmt.Sprint(cllected_count) | |||||
| } | |||||
| if len(datasetInfo) > 0 { | |||||
| datasetInfoJson, _ := json.Marshal(datasetInfo) | |||||
| return string(datasetInfoJson), score | |||||
| } else { | |||||
| return "", score | |||||
| } | |||||
| } | |||||
| func getRepoDetailInfo(repoDetailInfoMap map[string]int, userId int64, mostDownload map[int64]string) string { | |||||
| repoDetailInfo := make(map[string]string) | |||||
| if total, ok := repoDetailInfoMap[fmt.Sprint(userId)+"_total"]; ok { | |||||
| repoDetailInfo["repo_total"] = fmt.Sprint(total) | |||||
| } | |||||
| if private, ok := repoDetailInfoMap[fmt.Sprint(userId)+"_is_private"]; ok { | |||||
| repoDetailInfo["repo_is_private"] = fmt.Sprint(private) | |||||
| } | |||||
| if public, ok := repoDetailInfoMap[fmt.Sprint(userId)+"_is_public"]; ok { | |||||
| repoDetailInfo["repo_is_public"] = fmt.Sprint(public) | |||||
| } | |||||
| if download, ok := repoDetailInfoMap[fmt.Sprint(userId)+"_total_download"]; ok { | |||||
| repoDetailInfo["repo_total_download"] = fmt.Sprint(download) | |||||
| } | |||||
| if mostdownload, ok := repoDetailInfoMap[fmt.Sprint(userId)+"_most_download"]; ok { | |||||
| repoDetailInfo["repo_most_download_count"] = fmt.Sprint(mostdownload) | |||||
| } | |||||
| if mostdownloadName, ok := mostDownload[userId]; ok { | |||||
| repoDetailInfo["repo_most_download_name"] = mostdownloadName | |||||
| } | |||||
| if len(repoDetailInfo) > 0 { | |||||
| repoDetailInfoJson, _ := json.Marshal(repoDetailInfo) | |||||
| return string(repoDetailInfoJson) | |||||
| } else { | |||||
| return "" | |||||
| } | |||||
| } | |||||
| func getMostActiveJson(userInfo map[string]int) string { | |||||
| mostActiveMap := make(map[string]string) | |||||
| if day, ok := userInfo["hour_day"]; ok { | |||||
| hour := userInfo["hour_hour"] | |||||
| month := userInfo["hour_month"] | |||||
| year := userInfo["hour_year"] | |||||
| delete(userInfo, "hour_day") | |||||
| delete(userInfo, "hour_hour") | |||||
| delete(userInfo, "hour_month") | |||||
| delete(userInfo, "hour_year") | |||||
| mostActiveMap["before_dawn"] = fmt.Sprint(year) + "/" + fmt.Sprint(month) + "/" + fmt.Sprint(day) + " " + fmt.Sprint(hour) | |||||
| } | |||||
| max := 0 | |||||
| max_day := "" | |||||
| for key, value := range userInfo { | |||||
| if value > max { | |||||
| max = value | |||||
| max_day = key | |||||
| } | |||||
| } | |||||
| mostActiveMap["most_active_day"] = max_day | |||||
| mostActiveMap["most_active_num"] = fmt.Sprint(max) | |||||
| mostActiveMapJson, _ := json.Marshal(mostActiveMap) | |||||
| return string(mostActiveMapJson) | |||||
| } | |||||
| func updateUserIndex(tableName string, statictisSess *xorm.Session, userId int64, userIndex float64) { | func updateUserIndex(tableName string, statictisSess *xorm.Session, userId int64, userIndex float64) { | ||||
| updateSql := "UPDATE public." + tableName + " set user_index=" + fmt.Sprint(userIndex*100) + " where id=" + fmt.Sprint(userId) | updateSql := "UPDATE public." + tableName + " set user_index=" + fmt.Sprint(userIndex*100) + " where id=" + fmt.Sprint(userId) | ||||
| statictisSess.Exec(updateSql) | statictisSess.Exec(updateSql) | ||||
| @@ -997,7 +1056,7 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||||
| DataDate := CountDate.Format("2006-01-02") | DataDate := CountDate.Format("2006-01-02") | ||||
| CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | ||||
| CommitCountMap := queryCommitAction(start_unix, end_unix, 5) | |||||
| CommitCountMap, _ := queryCommitAction(start_unix, end_unix, 5) | |||||
| IssueCountMap := queryCreateIssue(start_unix, end_unix) | IssueCountMap := queryCreateIssue(start_unix, end_unix) | ||||
| CommentCountMap := queryComment(start_unix, end_unix) | CommentCountMap := queryComment(start_unix, end_unix) | ||||
| @@ -1010,19 +1069,19 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||||
| log.Info("query commit code errr.") | log.Info("query commit code errr.") | ||||
| } else { | } else { | ||||
| //log.Info("query commit code size, len=" + fmt.Sprint(len(CommitCodeSizeMap))) | //log.Info("query commit code size, len=" + fmt.Sprint(len(CommitCodeSizeMap))) | ||||
| CommitCodeSizeMapJson, _ := json.Marshal(CommitCodeSizeMap) | |||||
| log.Info("CommitCodeSizeMapJson=" + string(CommitCodeSizeMapJson)) | |||||
| //CommitCodeSizeMapJson, _ := json.Marshal(CommitCodeSizeMap) | |||||
| //log.Info("CommitCodeSizeMapJson=" + string(CommitCodeSizeMapJson)) | |||||
| } | } | ||||
| CommitDatasetSizeMap, CommitDatasetNumMap := queryDatasetSize(start_unix, end_unix) | |||||
| CommitDatasetSizeMap, CommitDatasetNumMap, _ := queryDatasetSize(start_unix, end_unix) | |||||
| SolveIssueCountMap := querySolveIssue(start_unix, end_unix) | SolveIssueCountMap := querySolveIssue(start_unix, end_unix) | ||||
| CreateRepoCountMap := queryUserCreateRepo(start_unix, end_unix) | |||||
| CreateRepoCountMap, _, _ := queryUserCreateRepo(start_unix, end_unix) | |||||
| LoginCountMap := queryLoginCount(start_unix, end_unix) | LoginCountMap := queryLoginCount(start_unix, end_unix) | ||||
| OpenIIndexMap := queryUserRepoOpenIIndex(start_unix, end_unix) | OpenIIndexMap := queryUserRepoOpenIIndex(start_unix, end_unix) | ||||
| CloudBrainTaskMap, CloudBrainTaskItemMap := queryCloudBrainTask(start_unix, end_unix) | CloudBrainTaskMap, CloudBrainTaskItemMap := queryCloudBrainTask(start_unix, end_unix) | ||||
| AiModelManageMap := queryUserModel(start_unix, end_unix) | AiModelManageMap := queryUserModel(start_unix, end_unix) | ||||
| CollectDataset, CollectedDataset := queryDatasetStars(start_unix, end_unix) | CollectDataset, CollectedDataset := queryDatasetStars(start_unix, end_unix) | ||||
| RecommendDataset := queryRecommedDataSet(start_unix, end_unix) | |||||
| RecommendDataset, _ := queryRecommedDataSet(start_unix, end_unix) | |||||
| CollectImage, CollectedImage := queryImageStars(start_unix, end_unix) | CollectImage, CollectedImage := queryImageStars(start_unix, end_unix) | ||||
| RecommendImage := queryRecommedImage(start_unix, end_unix) | RecommendImage := queryRecommedImage(start_unix, end_unix) | ||||
| @@ -1490,41 +1549,65 @@ func queryPullRequest(start_unix int64, end_unix int64) map[int64]int { | |||||
| return resultMap | return resultMap | ||||
| } | } | ||||
| func queryCommitAction(start_unix int64, end_unix int64, actionType int64) map[int64]int { | |||||
| func queryCommitAction(start_unix int64, end_unix int64, actionType int64) (map[int64]int, map[int64]map[string]int) { | |||||
| sess := x.NewSession() | sess := x.NewSession() | ||||
| defer sess.Close() | defer sess.Close() | ||||
| resultMap := make(map[int64]int) | resultMap := make(map[int64]int) | ||||
| cond := "user_id=act_user_id and op_type=" + fmt.Sprint(actionType) + " and created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | |||||
| mostActiveMap := make(map[int64]map[string]int) | |||||
| cond := "user_id=act_user_id and created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | |||||
| count, err := sess.Where(cond).Count(new(Action)) | count, err := sess.Where(cond).Count(new(Action)) | ||||
| if err != nil { | if err != nil { | ||||
| log.Info("query action error. return.") | log.Info("query action error. return.") | ||||
| return resultMap | |||||
| return resultMap, mostActiveMap | |||||
| } | } | ||||
| var indexTotal int64 | var indexTotal int64 | ||||
| indexTotal = 0 | indexTotal = 0 | ||||
| for { | for { | ||||
| sess.Select("id,user_id,op_type,act_user_id").Table("action").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
| sess.Select("id,user_id,op_type,act_user_id,created_unix").Table("action").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
| actionList := make([]*Action, 0) | actionList := make([]*Action, 0) | ||||
| sess.Find(&actionList) | sess.Find(&actionList) | ||||
| log.Info("query action size=" + fmt.Sprint(len(actionList))) | log.Info("query action size=" + fmt.Sprint(len(actionList))) | ||||
| for _, actionRecord := range actionList { | for _, actionRecord := range actionList { | ||||
| if _, ok := resultMap[actionRecord.UserID]; !ok { | |||||
| resultMap[actionRecord.UserID] = 1 | |||||
| if int64(actionRecord.OpType) == actionType { | |||||
| if _, ok := resultMap[actionRecord.UserID]; !ok { | |||||
| resultMap[actionRecord.UserID] = 1 | |||||
| } else { | |||||
| resultMap[actionRecord.UserID] += 1 | |||||
| } | |||||
| } | |||||
| key := getDate(actionRecord.CreatedUnix) | |||||
| if _, ok := mostActiveMap[actionRecord.UserID]; !ok { | |||||
| tmpMap := make(map[string]int) | |||||
| tmpMap[key] = 1 | |||||
| mostActiveMap[actionRecord.UserID] = tmpMap | |||||
| } else { | } else { | ||||
| resultMap[actionRecord.UserID] += 1 | |||||
| mostActiveMap[actionRecord.UserID][key] = getMapKeyStringValue(key, mostActiveMap[actionRecord.UserID]) + 1 | |||||
| } | |||||
| utcTime := actionRecord.CreatedUnix.AsTime() | |||||
| hour := utcTime.Hour() | |||||
| if hour >= 0 && hour <= 5 { | |||||
| key = "hour_hour" | |||||
| if getMapKeyStringValue(key, mostActiveMap[actionRecord.UserID]) < hour { | |||||
| mostActiveMap[actionRecord.UserID][key] = hour | |||||
| mostActiveMap[actionRecord.UserID]["hour_day"] = utcTime.Day() | |||||
| mostActiveMap[actionRecord.UserID]["hour_month"] = int(utcTime.Month()) | |||||
| mostActiveMap[actionRecord.UserID]["hour_year"] = utcTime.Year() | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| indexTotal += PAGE_SIZE | indexTotal += PAGE_SIZE | ||||
| if indexTotal >= count { | if indexTotal >= count { | ||||
| break | break | ||||
| } | } | ||||
| } | } | ||||
| return resultMap | |||||
| return resultMap, mostActiveMap | |||||
| } | |||||
| func getDate(createTime timeutil.TimeStamp) string { | |||||
| return createTime.Format("2006-01-02") | |||||
| } | } | ||||
| func queryCreateIssue(start_unix int64, end_unix int64) map[int64]int { | func queryCreateIssue(start_unix int64, end_unix int64) map[int64]int { | ||||
| @@ -1714,15 +1797,16 @@ func queryFollow(start_unix int64, end_unix int64) (map[int64]int, map[int64]int | |||||
| return resultMap, resultFocusedByOtherMap | return resultMap, resultFocusedByOtherMap | ||||
| } | } | ||||
| func queryRecommedDataSet(start_unix int64, end_unix int64) map[int64]int { | |||||
| func queryRecommedDataSet(start_unix int64, end_unix int64) (map[int64]int, map[int64]int) { | |||||
| sess := x.NewSession() | sess := x.NewSession() | ||||
| defer sess.Close() | defer sess.Close() | ||||
| userIdDdatasetMap := make(map[int64]int) | |||||
| cond := " created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) + " and recommend=true" | |||||
| userIdRecommentDatasetMap := make(map[int64]int) | |||||
| userIdCreateDatasetMap := make(map[int64]int) | |||||
| cond := " created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | |||||
| count, err := sess.Where(cond).Count(new(Dataset)) | count, err := sess.Where(cond).Count(new(Dataset)) | ||||
| if err != nil { | if err != nil { | ||||
| log.Info("query recommend dataset error. return.") | log.Info("query recommend dataset error. return.") | ||||
| return userIdDdatasetMap | |||||
| return userIdRecommentDatasetMap, userIdCreateDatasetMap | |||||
| } | } | ||||
| var indexTotal int64 | var indexTotal int64 | ||||
| indexTotal = 0 | indexTotal = 0 | ||||
| @@ -1732,18 +1816,21 @@ func queryRecommedDataSet(start_unix int64, end_unix int64) map[int64]int { | |||||
| sess.Find(&datasetList) | sess.Find(&datasetList) | ||||
| log.Info("query datasetList size=" + fmt.Sprint(len(datasetList))) | log.Info("query datasetList size=" + fmt.Sprint(len(datasetList))) | ||||
| for _, datasetRecord := range datasetList { | for _, datasetRecord := range datasetList { | ||||
| if _, ok := userIdDdatasetMap[datasetRecord.UserID]; !ok { | |||||
| userIdDdatasetMap[datasetRecord.UserID] = 1 | |||||
| } else { | |||||
| userIdDdatasetMap[datasetRecord.UserID] += 1 | |||||
| if datasetRecord.Recommend { | |||||
| if _, ok := userIdRecommentDatasetMap[datasetRecord.UserID]; !ok { | |||||
| userIdRecommentDatasetMap[datasetRecord.UserID] = 1 | |||||
| } else { | |||||
| userIdRecommentDatasetMap[datasetRecord.UserID] += 1 | |||||
| } | |||||
| } | } | ||||
| userIdCreateDatasetMap[datasetRecord.UserID] = getMapValue(datasetRecord.UserID, userIdCreateDatasetMap) + 1 | |||||
| } | } | ||||
| indexTotal += PAGE_SIZE | indexTotal += PAGE_SIZE | ||||
| if indexTotal >= count { | if indexTotal >= count { | ||||
| break | break | ||||
| } | } | ||||
| } | } | ||||
| return userIdDdatasetMap | |||||
| return userIdRecommentDatasetMap, userIdCreateDatasetMap | |||||
| } | } | ||||
| func queryAllDataSet() (map[int64]int64, map[int64]int64) { | func queryAllDataSet() (map[int64]int64, map[int64]int64) { | ||||
| @@ -1922,22 +2009,23 @@ func queryImageStars(start_unix int64, end_unix int64) (map[int64]int, map[int64 | |||||
| return imageCollect, imageCollected | return imageCollect, imageCollected | ||||
| } | } | ||||
| func queryDatasetSize(start_unix int64, end_unix int64) (map[int64]int, map[int64]int) { | |||||
| func queryDatasetSize(start_unix int64, end_unix int64) (map[int64]int, map[int64]int, map[int64]int) { | |||||
| sess := x.NewSession() | sess := x.NewSession() | ||||
| defer sess.Close() | defer sess.Close() | ||||
| resultSizeMap := make(map[int64]int) | resultSizeMap := make(map[int64]int) | ||||
| resultNumMap := make(map[int64]int) | resultNumMap := make(map[int64]int) | ||||
| resultDownloadMap := make(map[int64]int) | |||||
| cond := " created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | cond := " created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | ||||
| count, err := sess.Where(cond).Count(new(Attachment)) | count, err := sess.Where(cond).Count(new(Attachment)) | ||||
| if err != nil { | if err != nil { | ||||
| log.Info("query attachment error. return.") | log.Info("query attachment error. return.") | ||||
| return resultSizeMap, resultNumMap | |||||
| return resultSizeMap, resultNumMap, resultDownloadMap | |||||
| } | } | ||||
| var indexTotal int64 | var indexTotal int64 | ||||
| indexTotal = 0 | indexTotal = 0 | ||||
| for { | for { | ||||
| sess.Select("id,uploader_id,size").Table("attachment").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
| sess.Select("id,uploader_id,size,download_count").Table("attachment").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
| attachmentList := make([]*Attachment, 0) | attachmentList := make([]*Attachment, 0) | ||||
| sess.Find(&attachmentList) | sess.Find(&attachmentList) | ||||
| @@ -1946,9 +2034,11 @@ func queryDatasetSize(start_unix int64, end_unix int64) (map[int64]int, map[int6 | |||||
| if _, ok := resultSizeMap[attachRecord.UploaderID]; !ok { | if _, ok := resultSizeMap[attachRecord.UploaderID]; !ok { | ||||
| resultSizeMap[attachRecord.UploaderID] = int(attachRecord.Size / (1024 * 1024)) //MB | resultSizeMap[attachRecord.UploaderID] = int(attachRecord.Size / (1024 * 1024)) //MB | ||||
| resultNumMap[attachRecord.UploaderID] = 1 | resultNumMap[attachRecord.UploaderID] = 1 | ||||
| resultDownloadMap[attachRecord.UploaderID] = int(attachRecord.DownloadCount) | |||||
| } else { | } else { | ||||
| resultSizeMap[attachRecord.UploaderID] += int(attachRecord.Size / (1024 * 1024)) //MB | resultSizeMap[attachRecord.UploaderID] += int(attachRecord.Size / (1024 * 1024)) //MB | ||||
| resultNumMap[attachRecord.UploaderID] += 1 | resultNumMap[attachRecord.UploaderID] += 1 | ||||
| resultDownloadMap[attachRecord.UploaderID] += int(attachRecord.DownloadCount) | |||||
| } | } | ||||
| } | } | ||||
| @@ -1958,32 +2048,50 @@ func queryDatasetSize(start_unix int64, end_unix int64) (map[int64]int, map[int6 | |||||
| } | } | ||||
| } | } | ||||
| return resultSizeMap, resultNumMap | |||||
| return resultSizeMap, resultNumMap, resultDownloadMap | |||||
| } | } | ||||
| func queryUserCreateRepo(start_unix int64, end_unix int64) map[int64]int { | |||||
| func queryUserCreateRepo(start_unix int64, end_unix int64) (map[int64]int, map[string]int, map[int64]string) { | |||||
| sess := x.NewSession() | sess := x.NewSession() | ||||
| defer sess.Close() | defer sess.Close() | ||||
| resultMap := make(map[int64]int) | resultMap := make(map[int64]int) | ||||
| detailInfoMap := make(map[string]int) | |||||
| mostDownloadMap := make(map[int64]string) | |||||
| cond := "is_fork=false and created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | cond := "is_fork=false and created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | ||||
| count, err := sess.Where(cond).Count(new(Repository)) | count, err := sess.Where(cond).Count(new(Repository)) | ||||
| if err != nil { | if err != nil { | ||||
| log.Info("query Repository error. return.") | log.Info("query Repository error. return.") | ||||
| return resultMap | |||||
| return resultMap, detailInfoMap, mostDownloadMap | |||||
| } | } | ||||
| var indexTotal int64 | var indexTotal int64 | ||||
| indexTotal = 0 | indexTotal = 0 | ||||
| for { | for { | ||||
| sess.Select("id,owner_id,name").Table("repository").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
| sess.Select("id,owner_id,name,is_private,clone_cnt").Table("repository").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
| repoList := make([]*Repository, 0) | repoList := make([]*Repository, 0) | ||||
| sess.Find(&repoList) | sess.Find(&repoList) | ||||
| log.Info("query Repository size=" + fmt.Sprint(len(repoList))) | log.Info("query Repository size=" + fmt.Sprint(len(repoList))) | ||||
| for _, repoRecord := range repoList { | for _, repoRecord := range repoList { | ||||
| if _, ok := resultMap[repoRecord.OwnerID]; !ok { | |||||
| resultMap[repoRecord.OwnerID] = 1 | |||||
| resultMap[repoRecord.OwnerID] = getMapValue(repoRecord.OwnerID, resultMap) + 1 | |||||
| key := fmt.Sprint(repoRecord.OwnerID) + "_total" | |||||
| detailInfoMap[key] = getMapKeyStringValue(key, detailInfoMap) + 1 | |||||
| if repoRecord.IsPrivate { | |||||
| key := fmt.Sprint(repoRecord.OwnerID) + "_is_private" | |||||
| detailInfoMap[key] = getMapKeyStringValue(key, detailInfoMap) + 1 | |||||
| } else { | } else { | ||||
| resultMap[repoRecord.OwnerID] += 1 | |||||
| key := fmt.Sprint(repoRecord.OwnerID) + "_is_public" | |||||
| detailInfoMap[key] = getMapKeyStringValue(key, detailInfoMap) + 1 | |||||
| } | |||||
| key = fmt.Sprint(repoRecord.OwnerID) + "_total_download" | |||||
| detailInfoMap[key] = getMapKeyStringValue(key, detailInfoMap) + int(repoRecord.CloneCnt) | |||||
| key = fmt.Sprint(repoRecord.OwnerID) + "_most_download" | |||||
| if int(repoRecord.CloneCnt) > getMapKeyStringValue(key, detailInfoMap) { | |||||
| detailInfoMap[key] = int(repoRecord.CloneCnt) | |||||
| mostDownloadMap[repoRecord.OwnerID] = repoRecord.DisplayName() | |||||
| } | } | ||||
| } | } | ||||
| indexTotal += PAGE_SIZE | indexTotal += PAGE_SIZE | ||||
| @@ -1992,7 +2100,7 @@ func queryUserCreateRepo(start_unix int64, end_unix int64) map[int64]int { | |||||
| } | } | ||||
| } | } | ||||
| return resultMap | |||||
| return resultMap, detailInfoMap, mostDownloadMap | |||||
| } | } | ||||
| func queryUserRepoOpenIIndex(start_unix int64, end_unix int64) map[int64]float64 { | func queryUserRepoOpenIIndex(start_unix int64, end_unix int64) map[int64]float64 { | ||||
| @@ -2180,6 +2288,7 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s | |||||
| setMapKey("CloudBrainRunTime", cloudTaskRecord.UserID, int(cloudTaskRecord.Duration), resultItemMap) | setMapKey("CloudBrainRunTime", cloudTaskRecord.UserID, int(cloudTaskRecord.Duration), resultItemMap) | ||||
| } | } | ||||
| if cloudTaskRecord.Type == 1 { //npu | if cloudTaskRecord.Type == 1 { //npu | ||||
| setMapKey("CloudBrainTwo", cloudTaskRecord.UserID, 1, resultItemMap) | |||||
| if cloudTaskRecord.JobType == "TRAIN" { | if cloudTaskRecord.JobType == "TRAIN" { | ||||
| setMapKey("NpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) | setMapKey("NpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) | ||||
| } else if cloudTaskRecord.JobType == "INFERENCE" { | } else if cloudTaskRecord.JobType == "INFERENCE" { | ||||
| @@ -2187,14 +2296,32 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s | |||||
| } else { | } else { | ||||
| setMapKey("NpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap) | setMapKey("NpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap) | ||||
| } | } | ||||
| } else { //type=0 gpu | |||||
| } else if cloudTaskRecord.Type == 0 { //type=0 gpu | |||||
| setMapKey("CloudBrainOne", cloudTaskRecord.UserID, 1, resultItemMap) | |||||
| if cloudTaskRecord.JobType == "TRAIN" { | if cloudTaskRecord.JobType == "TRAIN" { | ||||
| setMapKey("GpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) | setMapKey("GpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) | ||||
| } else if cloudTaskRecord.JobType == "INFERENCE" { | |||||
| setMapKey("GpuInferenceJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||||
| } else if cloudTaskRecord.JobType == "BENCHMARK" { | } else if cloudTaskRecord.JobType == "BENCHMARK" { | ||||
| setMapKey("GpuBenchMarkJob", cloudTaskRecord.UserID, 1, resultItemMap) | setMapKey("GpuBenchMarkJob", cloudTaskRecord.UserID, 1, resultItemMap) | ||||
| } else { | } else { | ||||
| setMapKey("GpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap) | setMapKey("GpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap) | ||||
| } | } | ||||
| } else if cloudTaskRecord.Type == 2 { | |||||
| setMapKey("C2Net", cloudTaskRecord.UserID, 1, resultItemMap) | |||||
| if cloudTaskRecord.ComputeResource == NPUResource { | |||||
| if cloudTaskRecord.JobType == "TRAIN" { | |||||
| setMapKey("NpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||||
| } else { | |||||
| setMapKey("NpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||||
| } | |||||
| } else if cloudTaskRecord.ComputeResource == GPUResource { | |||||
| if cloudTaskRecord.JobType == "TRAIN" { | |||||
| setMapKey("GpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||||
| } else { | |||||
| setMapKey("GpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| indexTotal += PAGE_SIZE | indexTotal += PAGE_SIZE | ||||
| @@ -2274,3 +2401,26 @@ func subMonth(t1, t2 time.Time) (month int) { | |||||
| } | } | ||||
| return month | return month | ||||
| } | } | ||||
| func GetContentFromPromote(url string) (string, error) { | |||||
| defer func() { | |||||
| if err := recover(); err != nil { | |||||
| log.Info("not error.", err) | |||||
| return | |||||
| } | |||||
| }() | |||||
| resp, err := http.Get(url) | |||||
| if err != nil || resp.StatusCode != 200 { | |||||
| log.Info("Get organizations url error=" + err.Error()) | |||||
| return "", err | |||||
| } | |||||
| bytes, err := ioutil.ReadAll(resp.Body) | |||||
| resp.Body.Close() | |||||
| if err != nil { | |||||
| log.Info("Get organizations url error=" + err.Error()) | |||||
| return "", err | |||||
| } | |||||
| allLineStr := string(bytes) | |||||
| return allLineStr, nil | |||||
| } | |||||
| @@ -2,6 +2,27 @@ package models | |||||
| import "code.gitea.io/gitea/modules/timeutil" | import "code.gitea.io/gitea/modules/timeutil" | ||||
| type UserSummaryCurrentYear struct { | |||||
| ID int64 `xorm:"pk"` | |||||
| Email string `xorm:"NOT NULL"` | |||||
| //user | |||||
| Name string `xorm:"NOT NULL"` | |||||
| Phone string `xorm:"NULL"` | |||||
| //user | |||||
| RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
| DateCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| MostActiveDay string `xorm:" NULL "` //08.05 | |||||
| RepoInfo string `xorm:"varchar(1000)"` //创建了XX 个项目,公开项目XX 个,私有项目XX 个累计被下载XXX 次,其中《XXXXXXX 》项目,获得了最高XXX 次下载 | |||||
| DataSetInfo string `xorm:"varchar(500)"` //创建了XX 个数据集,上传了XX 个数据集文件,累计被下载XX 次,被收藏XX 次 | |||||
| CodeInfo string `xorm:"varchar(500)"` //代码提交次数,提交总代码行数,最晚的提交时间 | |||||
| CloudBrainInfo string `xorm:"varchar(1000)"` //,创建了XX 个云脑任务,调试任务XX 个,训练任务XX 个,推理任务XX 个,累计运行了XXXX 卡时,累计节省xxxxx 元 | |||||
| //这些免费的算力资源分别有,XX% 来自鹏城云脑1,XX% 来自鹏城云脑2,XX% 来自智算网络 | |||||
| PlayARoll string `xorm:"varchar(500)"` //你参加了XX 次“我为开源打榜狂”活动,累计上榜XX 次,总共获得了社区XXX 元的激励 | |||||
| Label string `xorm:"varchar(500)"` | |||||
| } | |||||
| type UserBusinessAnalysisCurrentYear struct { | type UserBusinessAnalysisCurrentYear struct { | ||||
| ID int64 `xorm:"pk"` | ID int64 `xorm:"pk"` | ||||
| CountDate int64 `xorm:"pk"` | CountDate int64 `xorm:"pk"` | ||||
| @@ -505,3 +526,182 @@ type UserMetrics struct { | |||||
| ActivityUserJson string `xorm:"text NULL"` //激活用户列表 | ActivityUserJson string `xorm:"text NULL"` //激活用户列表 | ||||
| CurrentDayRegistUser int `xorm:"NOT NULL DEFAULT 0"` //当天注册用户 | CurrentDayRegistUser int `xorm:"NOT NULL DEFAULT 0"` //当天注册用户 | ||||
| } | } | ||||
| type UserBusinessAnalysisAll struct { | |||||
| ID int64 `xorm:"pk"` | |||||
| CountDate int64 `xorm:"pk"` | |||||
| //action :ActionMergePullRequest // 11 | |||||
| CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //action :ActionCommitRepo // 5 | |||||
| CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //action :ActionCreateIssue // 10 | |||||
| IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //comment table current date | |||||
| CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //watch table current date | |||||
| FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //star table current date | |||||
| StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //follow table | |||||
| WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| // user table | |||||
| GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||||
| // | |||||
| CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //attachement table | |||||
| CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //0 | |||||
| CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //issue, issueassignees | |||||
| SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //baike | |||||
| EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //user | |||||
| RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
| //repo | |||||
| CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //login count, from elk | |||||
| LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //openi index | |||||
| OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| //user | |||||
| Email string `xorm:"NOT NULL"` | |||||
| //user | |||||
| Name string `xorm:"NOT NULL"` | |||||
| DataDate string `xorm:"NULL"` | |||||
| //cloudbraintask | |||||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserIndexPrimitive float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserLocation string `xorm:"NULL"` | |||||
| FocusOtherUser int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectedDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| RecommendDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectedImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| RecommendImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| Phone string `xorm:"NULL"` | |||||
| InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| } | |||||
| type UserBusinessAnalysis struct { | |||||
| ID int64 `xorm:"pk"` | |||||
| DataDate string `xorm:"pk"` | |||||
| CountDate int64 `xorm:"NULL"` | |||||
| //action :ActionMergePullRequest // 11 | |||||
| CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //action :ActionCommitRepo // 5 | |||||
| CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //action :ActionCreateIssue // 6 | |||||
| IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //comment table current date | |||||
| CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //watch table current date | |||||
| FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //star table current date | |||||
| StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //follow table | |||||
| WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| // user table | |||||
| GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||||
| // | |||||
| CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //attachement table | |||||
| CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //0 | |||||
| CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //issue, issueassignees | |||||
| SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //baike | |||||
| EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //user | |||||
| RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
| //repo | |||||
| CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //login count, from elk | |||||
| LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
| //openi index | |||||
| OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| //user | |||||
| Email string `xorm:"NOT NULL"` | |||||
| //user | |||||
| Name string `xorm:"NOT NULL"` | |||||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserIndexPrimitive float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| UserLocation string `xorm:"NULL"` | |||||
| FocusOtherUser int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectedDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| RecommendDataset int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| CollectedImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| RecommendImage int `xorm:"NOT NULL DEFAULT 0"` | |||||
| Phone string `xorm:"NULL"` | |||||
| InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"` | |||||
| } | |||||
| @@ -245,6 +245,32 @@ func GetTrainJobLog(jobID string) (string, error) { | |||||
| return logContent, nil | return logContent, nil | ||||
| } | } | ||||
| func GetGrampusMetrics(jobID string) (models.GetTrainJobMetricStatisticResult, error) { | |||||
| checkSetting() | |||||
| client := getRestyClient() | |||||
| var result models.GetTrainJobMetricStatisticResult | |||||
| res, err := client.R(). | |||||
| SetAuthToken(TOKEN). | |||||
| Get(HOST + urlTrainJob + "/" + jobID + "/task/0/replica/0/metrics") | |||||
| if err != nil { | |||||
| return result, fmt.Errorf("resty GetTrainJobLog: %v", err) | |||||
| } | |||||
| if err = json.Unmarshal([]byte(res.String()), &result); err != nil { | |||||
| log.Error("GetGrampusMetrics json.Unmarshal failed(%s): %v", res.String(), err.Error()) | |||||
| return result, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error()) | |||||
| } | |||||
| if res.StatusCode() != http.StatusOK { | |||||
| log.Error("Call GrampusMetrics failed(%d):%s(%s)", res.StatusCode(), result.ErrorCode, result.ErrorMsg) | |||||
| return result, fmt.Errorf("Call GrampusMetrics failed(%d):%d(%s)", res.StatusCode(), result.ErrorCode, result.ErrorMsg) | |||||
| } | |||||
| if !result.IsSuccess { | |||||
| log.Error("GetGrampusMetrics(%s) failed", jobID) | |||||
| return result, fmt.Errorf("GetGrampusMetrics failed:%s", result.ErrorMsg) | |||||
| } | |||||
| return result, nil | |||||
| } | |||||
| func StopJob(jobID string) (*models.GrampusStopJobResponse, error) { | func StopJob(jobID string) (*models.GrampusStopJobResponse, error) { | ||||
| checkSetting() | checkSetting() | ||||
| client := getRestyClient() | client := getRestyClient() | ||||
| @@ -598,20 +598,23 @@ var ( | |||||
| //grampus config | //grampus config | ||||
| Grampus = struct { | Grampus = struct { | ||||
| Env string | |||||
| Host string | |||||
| UserName string | |||||
| Password string | |||||
| SpecialPools string | |||||
| C2NetSequence string | |||||
| SyncScriptProject string | |||||
| LocalCenterID string | |||||
| AiCenterInfo string | |||||
| Env string | |||||
| Host string | |||||
| UserName string | |||||
| Password string | |||||
| SpecialPools string | |||||
| C2NetSequence string | |||||
| SyncScriptProject string | |||||
| LocalCenterID string | |||||
| AiCenterInfo string | |||||
| AiCenterCodeAndNameInfo string | |||||
| UsageRateBeginTime string | |||||
| }{} | }{} | ||||
| C2NetInfos *C2NetSqInfos | |||||
| CenterInfos *AiCenterInfos | |||||
| C2NetMapInfo map[string]*C2NetSequenceInfo | |||||
| C2NetInfos *C2NetSqInfos | |||||
| CenterInfos *AiCenterInfos | |||||
| C2NetMapInfo map[string]*C2NetSequenceInfo | |||||
| AiCenterCodeAndNameMapInfo map[string]*C2NetSequenceInfo | |||||
| //elk config | //elk config | ||||
| ElkUrl string | ElkUrl string | ||||
| @@ -1466,7 +1469,7 @@ func NewContext() { | |||||
| MaxDuration = sec.Key("MAX_DURATION").MustInt64(14400) | MaxDuration = sec.Key("MAX_DURATION").MustInt64(14400) | ||||
| TrainGpuTypes = sec.Key("TRAIN_GPU_TYPES").MustString("") | TrainGpuTypes = sec.Key("TRAIN_GPU_TYPES").MustString("") | ||||
| TrainResourceSpecs = sec.Key("TRAIN_RESOURCE_SPECS").MustString("") | TrainResourceSpecs = sec.Key("TRAIN_RESOURCE_SPECS").MustString("") | ||||
| MaxModelSize = sec.Key("MAX_MODEL_SIZE").MustFloat64(500) | |||||
| MaxModelSize = sec.Key("MAX_MODEL_SIZE").MustFloat64(200) | |||||
| InferenceGpuTypes = sec.Key("INFERENCE_GPU_TYPES").MustString("") | InferenceGpuTypes = sec.Key("INFERENCE_GPU_TYPES").MustString("") | ||||
| InferenceResourceSpecs = sec.Key("INFERENCE_RESOURCE_SPECS").MustString("") | InferenceResourceSpecs = sec.Key("INFERENCE_RESOURCE_SPECS").MustString("") | ||||
| SpecialPools = sec.Key("SPECIAL_POOL").MustString("") | SpecialPools = sec.Key("SPECIAL_POOL").MustString("") | ||||
| @@ -1680,6 +1683,8 @@ func getGrampusConfig() { | |||||
| Grampus.Password = sec.Key("PASSWORD").MustString("") | Grampus.Password = sec.Key("PASSWORD").MustString("") | ||||
| Grampus.SpecialPools = sec.Key("SPECIAL_POOL").MustString("") | Grampus.SpecialPools = sec.Key("SPECIAL_POOL").MustString("") | ||||
| Grampus.C2NetSequence = sec.Key("C2NET_SEQUENCE").MustString("{\"sequence\":[{\"id\":1,\"name\":\"cloudbrain_one\",\"content\":\"鹏城云脑一号\",\"content_en\":\"Pencheng Cloudbrain Ⅰ\"},{\"id\":2,\"name\":\"cloudbrain_two\",\"content\":\"鹏城云脑二号\",\"content_en\":\"Pencheng Cloudbrain Ⅱ\"},{\"id\":3,\"name\":\"beida\",\"content\":\"北大人工智能集群系统\",\"content_en\":\"Peking University AI Center\"},{\"id\":4,\"name\":\"hefei\",\"content\":\"合肥类脑智能开放平台\",\"content_en\":\"Hefei AI Center\"},{\"id\":5,\"name\":\"wuhan\",\"content\":\"武汉人工智能计算中心\",\"content_en\":\"Wuhan AI Center\"},{\"id\":6,\"name\":\"xian\",\"content\":\"西安未来人工智能计算中心\",\"content_en\":\"Xi'an AI Center\"},{\"id\":7,\"pclcci\":\"more\",\"content\":\"鹏城云计算所\",\"content_en\":\"Pengcheng Cloud Computing Institute\"},{\"id\":8,\"name\":\"xuchang\",\"content\":\"中原人工智能计算中心\",\"content_en\":\"Zhongyuan AI Center\"},{\"id\":9,\"name\":\"chengdu\",\"content\":\"成都人工智能计算中心\",\"content_en\":\"Chengdu AI Center\"},{\"id\":10,\"name\":\"more\",\"content\":\"横琴先进智能计算中心\",\"content_en\":\"Hengqin AI Center\"},{\"id\":11,\"name\":\"more\",\"content\":\"国家超级计算济南中心\",\"content_en\":\"HPC & AI Center\"}]}") | Grampus.C2NetSequence = sec.Key("C2NET_SEQUENCE").MustString("{\"sequence\":[{\"id\":1,\"name\":\"cloudbrain_one\",\"content\":\"鹏城云脑一号\",\"content_en\":\"Pencheng Cloudbrain Ⅰ\"},{\"id\":2,\"name\":\"cloudbrain_two\",\"content\":\"鹏城云脑二号\",\"content_en\":\"Pencheng Cloudbrain Ⅱ\"},{\"id\":3,\"name\":\"beida\",\"content\":\"北大人工智能集群系统\",\"content_en\":\"Peking University AI Center\"},{\"id\":4,\"name\":\"hefei\",\"content\":\"合肥类脑智能开放平台\",\"content_en\":\"Hefei AI Center\"},{\"id\":5,\"name\":\"wuhan\",\"content\":\"武汉人工智能计算中心\",\"content_en\":\"Wuhan AI Center\"},{\"id\":6,\"name\":\"xian\",\"content\":\"西安未来人工智能计算中心\",\"content_en\":\"Xi'an AI Center\"},{\"id\":7,\"pclcci\":\"more\",\"content\":\"鹏城云计算所\",\"content_en\":\"Pengcheng Cloud Computing Institute\"},{\"id\":8,\"name\":\"xuchang\",\"content\":\"中原人工智能计算中心\",\"content_en\":\"Zhongyuan AI Center\"},{\"id\":9,\"name\":\"chengdu\",\"content\":\"成都人工智能计算中心\",\"content_en\":\"Chengdu AI Center\"},{\"id\":10,\"name\":\"more\",\"content\":\"横琴先进智能计算中心\",\"content_en\":\"Hengqin AI Center\"},{\"id\":11,\"name\":\"more\",\"content\":\"国家超级计算济南中心\",\"content_en\":\"HPC & AI Center\"}]}") | ||||
| Grampus.AiCenterCodeAndNameInfo = sec.Key("AI_CENTER_CODE_AND_NAME").MustString("{\"sequence\":[{\"id\":1,\"name\":\"cloudbrain_one\",\"content\":\"鹏城云脑一号\",\"content_en\":\"Pencheng Cloudbrain Ⅰ\"},{\"id\":2,\"name\":\"cloudbrain_two\",\"content\":\"鹏城云脑二号\",\"content_en\":\"Pencheng Cloudbrain Ⅱ\"},{\"id\":3,\"name\":\"beida\",\"content\":\"北大人工智能集群系统\",\"content_en\":\"Peking University AI Center\"},{\"id\":4,\"name\":\"hefei\",\"content\":\"合肥类脑智能开放平台\",\"content_en\":\"Hefei AI Center\"},{\"id\":5,\"name\":\"wuhan\",\"content\":\"武汉人工智能计算中心\",\"content_en\":\"Wuhan AI Center\"},{\"id\":6,\"name\":\"xian\",\"content\":\"西安未来人工智能计算中心\",\"content_en\":\"Xi'an AI Center\"},{\"id\":7,\"pclcci\":\"more\",\"content\":\"鹏城云计算所\",\"content_en\":\"Pengcheng Cloud Computing Institute\"},{\"id\":8,\"name\":\"xuchang\",\"content\":\"中原人工智能计算中心\",\"content_en\":\"Zhongyuan AI Center\"},{\"id\":9,\"name\":\"chengdu\",\"content\":\"成都人工智能计算中心\",\"content_en\":\"Chengdu AI Center\"},{\"id\":10,\"name\":\"more\",\"content\":\"横琴先进智能计算中心\",\"content_en\":\"Hengqin AI Center\"},{\"id\":11,\"name\":\"more\",\"content\":\"国家超级计算济南中心\",\"content_en\":\"HPC & AI Center\"}]}") | |||||
| Grampus.UsageRateBeginTime = sec.Key("USAGE_RATE_BEGIN_TIME").MustString("2021-01-01 00:00:00") | |||||
| if Grampus.C2NetSequence != "" { | if Grampus.C2NetSequence != "" { | ||||
| if err := json.Unmarshal([]byte(Grampus.C2NetSequence), &C2NetInfos); err != nil { | if err := json.Unmarshal([]byte(Grampus.C2NetSequence), &C2NetInfos); err != nil { | ||||
| log.Error("Unmarshal(C2NetSequence) failed:%v", err) | log.Error("Unmarshal(C2NetSequence) failed:%v", err) | ||||
| @@ -1689,6 +1694,15 @@ func getGrampusConfig() { | |||||
| C2NetMapInfo[value.Name] = value | C2NetMapInfo[value.Name] = value | ||||
| } | } | ||||
| } | } | ||||
| if Grampus.AiCenterCodeAndNameInfo != "" { | |||||
| if err := json.Unmarshal([]byte(Grampus.AiCenterCodeAndNameInfo), &C2NetInfos); err != nil { | |||||
| log.Error("Unmarshal(AiCenterCodeAndNameInfo) failed:%v", err) | |||||
| } | |||||
| AiCenterCodeAndNameMapInfo = make(map[string]*C2NetSequenceInfo) | |||||
| for _, value := range C2NetInfos.C2NetSqInfo { | |||||
| AiCenterCodeAndNameMapInfo[value.Name] = value | |||||
| } | |||||
| } | |||||
| Grampus.SyncScriptProject = sec.Key("SYNC_SCRIPT_PROJECT").MustString("script_for_grampus") | Grampus.SyncScriptProject = sec.Key("SYNC_SCRIPT_PROJECT").MustString("script_for_grampus") | ||||
| Grampus.LocalCenterID = sec.Key("LOCAL_CENTER_ID").MustString("cloudbrain2") | Grampus.LocalCenterID = sec.Key("LOCAL_CENTER_ID").MustString("cloudbrain2") | ||||
| Grampus.AiCenterInfo = sec.Key("AI_CENTER_INFO").MustString("") | Grampus.AiCenterInfo = sec.Key("AI_CENTER_INFO").MustString("") | ||||
| @@ -144,8 +144,8 @@ func (m *MinioStorage) HasObject(path string) (bool, error) { | |||||
| // Indicate to our routine to exit cleanly upon return. | // Indicate to our routine to exit cleanly upon return. | ||||
| defer close(doneCh) | defer close(doneCh) | ||||
| objectCh := m.client.ListObjects(m.bucket, m.buildMinioPath(path), false, doneCh) | |||||
| //objectCh := m.client.ListObjects(m.bucket, m.buildMinioPath(path), false, doneCh) | |||||
| objectCh := m.client.ListObjects(m.bucket, path, false, doneCh) | |||||
| for object := range objectCh { | for object := range objectCh { | ||||
| if object.Err != nil { | if object.Err != nil { | ||||
| return hasObject, object.Err | return hasObject, object.Err | ||||
| @@ -3,7 +3,6 @@ package storage | |||||
| import ( | import ( | ||||
| "encoding/xml" | "encoding/xml" | ||||
| "errors" | "errors" | ||||
| "path" | |||||
| "sort" | "sort" | ||||
| "strconv" | "strconv" | ||||
| "strings" | "strings" | ||||
| @@ -101,7 +100,7 @@ func getClients() (*minio_ext.Client, *miniov6.Core, error) { | |||||
| return client, core, nil | return client, core, nil | ||||
| } | } | ||||
| func GenMultiPartSignedUrl(uuid string, uploadId string, partNumber int, partSize int64) (string, error) { | |||||
| func GenMultiPartSignedUrl(objectName string, uploadId string, partNumber int, partSize int64) (string, error) { | |||||
| minioClient, _, err := getClients() | minioClient, _, err := getClients() | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("getClients failed:", err.Error()) | log.Error("getClients failed:", err.Error()) | ||||
| @@ -110,7 +109,7 @@ func GenMultiPartSignedUrl(uuid string, uploadId string, partNumber int, partSiz | |||||
| minio := setting.Attachment.Minio | minio := setting.Attachment.Minio | ||||
| bucketName := minio.Bucket | bucketName := minio.Bucket | ||||
| objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/") | |||||
| //objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/") | |||||
| return minioClient.GenUploadPartSignedUrl(uploadId, bucketName, objectName, partNumber, partSize, PresignedUploadPartUrlExpireTime, setting.Attachment.Minio.Location) | return minioClient.GenUploadPartSignedUrl(uploadId, bucketName, objectName, partNumber, partSize, PresignedUploadPartUrlExpireTime, setting.Attachment.Minio.Location) | ||||
| } | } | ||||
| @@ -268,6 +267,23 @@ func MinioCopyFiles(bucketName string, srcPath string, destPath string, Files [] | |||||
| return fileTotalSize, nil | return fileTotalSize, nil | ||||
| } | } | ||||
| func MinioCopyAFile(srcBucketName, srcObjectName, destBucketName, destObjectName string) (int64, error) { | |||||
| _, core, err := getClients() | |||||
| var fileTotalSize int64 | |||||
| fileTotalSize = 0 | |||||
| if err != nil { | |||||
| log.Error("getClients failed:", err.Error()) | |||||
| return fileTotalSize, err | |||||
| } | |||||
| meta, err := core.StatObject(srcBucketName, srcObjectName, miniov6.StatObjectOptions{}) | |||||
| if err != nil { | |||||
| log.Info("Get file error:" + err.Error()) | |||||
| } | |||||
| core.CopyObject(srcBucketName, srcObjectName, destBucketName, destObjectName, meta.UserMetadata) | |||||
| fileTotalSize = meta.Size | |||||
| return fileTotalSize, nil | |||||
| } | |||||
| func MinioPathCopy(bucketName string, srcPath string, destPath string) (int64, error) { | func MinioPathCopy(bucketName string, srcPath string, destPath string) (int64, error) { | ||||
| _, core, err := getClients() | _, core, err := getClients() | ||||
| var fileTotalSize int64 | var fileTotalSize int64 | ||||
| @@ -301,7 +317,7 @@ func MinioPathCopy(bucketName string, srcPath string, destPath string) (int64, e | |||||
| return fileTotalSize, nil | return fileTotalSize, nil | ||||
| } | } | ||||
| func NewMultiPartUpload(uuid string) (string, error) { | |||||
| func NewMultiPartUpload(objectName string) (string, error) { | |||||
| _, core, err := getClients() | _, core, err := getClients() | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("getClients failed:", err.Error()) | log.Error("getClients failed:", err.Error()) | ||||
| @@ -310,12 +326,12 @@ func NewMultiPartUpload(uuid string) (string, error) { | |||||
| minio := setting.Attachment.Minio | minio := setting.Attachment.Minio | ||||
| bucketName := minio.Bucket | bucketName := minio.Bucket | ||||
| objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/") | |||||
| //objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/") | |||||
| return core.NewMultipartUpload(bucketName, objectName, miniov6.PutObjectOptions{}) | return core.NewMultipartUpload(bucketName, objectName, miniov6.PutObjectOptions{}) | ||||
| } | } | ||||
| func CompleteMultiPartUpload(uuid string, uploadID string, totalChunks int) (string, error) { | |||||
| func CompleteMultiPartUpload(objectName string, uploadID string, totalChunks int) (string, error) { | |||||
| client, core, err := getClients() | client, core, err := getClients() | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("getClients failed:", err.Error()) | log.Error("getClients failed:", err.Error()) | ||||
| @@ -324,8 +340,8 @@ func CompleteMultiPartUpload(uuid string, uploadID string, totalChunks int) (str | |||||
| minio := setting.Attachment.Minio | minio := setting.Attachment.Minio | ||||
| bucketName := minio.Bucket | bucketName := minio.Bucket | ||||
| objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/") | |||||
| //objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/") | |||||
| log.Info("bucketName=" + bucketName + " objectName=" + objectName + " uploadID=" + uploadID) | |||||
| partInfos, err := client.ListObjectParts(bucketName, objectName, uploadID) | partInfos, err := client.ListObjectParts(bucketName, objectName, uploadID) | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("ListObjectParts failed:", err.Error()) | log.Error("ListObjectParts failed:", err.Error()) | ||||
| @@ -351,7 +367,7 @@ func CompleteMultiPartUpload(uuid string, uploadID string, totalChunks int) (str | |||||
| return core.CompleteMultipartUpload(bucketName, objectName, uploadID, complMultipartUpload.Parts) | return core.CompleteMultipartUpload(bucketName, objectName, uploadID, complMultipartUpload.Parts) | ||||
| } | } | ||||
| func GetPartInfos(uuid string, uploadID string) (string, error) { | |||||
| func GetPartInfos(objectName string, uploadID string) (string, error) { | |||||
| minioClient, _, err := getClients() | minioClient, _, err := getClients() | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("getClients failed:", err.Error()) | log.Error("getClients failed:", err.Error()) | ||||
| @@ -360,7 +376,7 @@ func GetPartInfos(uuid string, uploadID string) (string, error) { | |||||
| minio := setting.Attachment.Minio | minio := setting.Attachment.Minio | ||||
| bucketName := minio.Bucket | bucketName := minio.Bucket | ||||
| objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/") | |||||
| //objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/") | |||||
| partInfos, err := minioClient.ListObjectParts(bucketName, objectName, uploadID) | partInfos, err := minioClient.ListObjectParts(bucketName, objectName, uploadID) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -90,17 +90,16 @@ func listAllParts(uuid, uploadID, key string) (output *obs.ListPartsOutput, err | |||||
| } else { | } else { | ||||
| continue | continue | ||||
| } | } | ||||
| break | |||||
| } | } | ||||
| return output, nil | return output, nil | ||||
| } | } | ||||
| func GetObsPartInfos(uuid, uploadID, fileName string) (string, error) { | |||||
| key := strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| func GetObsPartInfos(objectName, uploadID string) (string, error) { | |||||
| key := objectName | |||||
| //strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| allParts, err := listAllParts(uuid, uploadID, key) | |||||
| allParts, err := listAllParts(objectName, uploadID, key) | |||||
| if err != nil { | if err != nil { | ||||
| log.Error("listAllParts failed: %v", err) | log.Error("listAllParts failed: %v", err) | ||||
| return "", err | return "", err | ||||
| @@ -114,10 +113,11 @@ func GetObsPartInfos(uuid, uploadID, fileName string) (string, error) { | |||||
| return chunks, nil | return chunks, nil | ||||
| } | } | ||||
| func NewObsMultiPartUpload(uuid, fileName string) (string, error) { | |||||
| func NewObsMultiPartUpload(objectName string) (string, error) { | |||||
| input := &obs.InitiateMultipartUploadInput{} | input := &obs.InitiateMultipartUploadInput{} | ||||
| input.Bucket = setting.Bucket | input.Bucket = setting.Bucket | ||||
| input.Key = strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| input.Key = objectName | |||||
| //strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| output, err := ObsCli.InitiateMultipartUpload(input) | output, err := ObsCli.InitiateMultipartUpload(input) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -128,13 +128,14 @@ func NewObsMultiPartUpload(uuid, fileName string) (string, error) { | |||||
| return output.UploadId, nil | return output.UploadId, nil | ||||
| } | } | ||||
| func CompleteObsMultiPartUpload(uuid, uploadID, fileName string, totalChunks int) error { | |||||
| func CompleteObsMultiPartUpload(objectName, uploadID string, totalChunks int) error { | |||||
| input := &obs.CompleteMultipartUploadInput{} | input := &obs.CompleteMultipartUploadInput{} | ||||
| input.Bucket = setting.Bucket | input.Bucket = setting.Bucket | ||||
| input.Key = strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| //input.Key = strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| input.Key = objectName | |||||
| input.UploadId = uploadID | input.UploadId = uploadID | ||||
| allParts, err := listAllParts(uuid, uploadID, input.Key) | |||||
| allParts, err := listAllParts(objectName, uploadID, input.Key) | |||||
| if err != nil { | if err != nil { | ||||
| log.Error("listAllParts failed: %v", err) | log.Error("listAllParts failed: %v", err) | ||||
| return err | return err | ||||
| @@ -153,15 +154,16 @@ func CompleteObsMultiPartUpload(uuid, uploadID, fileName string, totalChunks int | |||||
| return err | return err | ||||
| } | } | ||||
| log.Info("uuid:%s, RequestId:%s", uuid, output.RequestId) | |||||
| log.Info("uuid:%s, RequestId:%s", objectName, output.RequestId) | |||||
| return nil | return nil | ||||
| } | } | ||||
| func ObsMultiPartUpload(uuid string, uploadId string, partNumber int, fileName string, putBody io.ReadCloser) error { | |||||
| func ObsMultiPartUpload(objectName string, uploadId string, partNumber int, fileName string, putBody io.ReadCloser) error { | |||||
| input := &obs.UploadPartInput{} | input := &obs.UploadPartInput{} | ||||
| input.Bucket = setting.Bucket | input.Bucket = setting.Bucket | ||||
| input.Key = strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| input.Key = objectName | |||||
| //strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| input.UploadId = uploadId | input.UploadId = uploadId | ||||
| input.PartNumber = partNumber | input.PartNumber = partNumber | ||||
| input.Body = putBody | input.Body = putBody | ||||
| @@ -241,11 +243,6 @@ func ObsDownloadAFile(bucket string, key string) (io.ReadCloser, error) { | |||||
| } | } | ||||
| } | } | ||||
| func ObsDownload(uuid string, fileName string) (io.ReadCloser, error) { | |||||
| return ObsDownloadAFile(setting.Bucket, strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/")) | |||||
| } | |||||
| func ObsModelDownload(JobName string, fileName string) (io.ReadCloser, error) { | func ObsModelDownload(JobName string, fileName string) (io.ReadCloser, error) { | ||||
| input := &obs.GetObjectInput{} | input := &obs.GetObjectInput{} | ||||
| input.Bucket = setting.Bucket | input.Bucket = setting.Bucket | ||||
| @@ -297,7 +294,7 @@ func ObsCopyManyFile(srcBucket string, srcPath string, destBucket string, destPa | |||||
| log.Info("Get File error, error=" + err.Error()) | log.Info("Get File error, error=" + err.Error()) | ||||
| continue | continue | ||||
| } | } | ||||
| obsCopyFile(srcBucket, srcKey, destBucket, destKey) | |||||
| ObsCopyFile(srcBucket, srcKey, destBucket, destKey) | |||||
| fileTotalSize += out.ContentLength | fileTotalSize += out.ContentLength | ||||
| } | } | ||||
| @@ -321,7 +318,7 @@ func ObsCopyAllFile(srcBucket string, srcPath string, destBucket string, destPat | |||||
| index++ | index++ | ||||
| for _, val := range output.Contents { | for _, val := range output.Contents { | ||||
| destKey := destPath + val.Key[length:] | destKey := destPath + val.Key[length:] | ||||
| obsCopyFile(srcBucket, val.Key, destBucket, destKey) | |||||
| ObsCopyFile(srcBucket, val.Key, destBucket, destKey) | |||||
| fileTotalSize += val.Size | fileTotalSize += val.Size | ||||
| } | } | ||||
| if output.IsTruncated { | if output.IsTruncated { | ||||
| @@ -340,7 +337,7 @@ func ObsCopyAllFile(srcBucket string, srcPath string, destBucket string, destPat | |||||
| return fileTotalSize, nil | return fileTotalSize, nil | ||||
| } | } | ||||
| func obsCopyFile(srcBucket string, srcKeyName string, destBucket string, destKeyName string) error { | |||||
| func ObsCopyFile(srcBucket string, srcKeyName string, destBucket string, destKeyName string) error { | |||||
| input := &obs.CopyObjectInput{} | input := &obs.CopyObjectInput{} | ||||
| input.Bucket = destBucket | input.Bucket = destBucket | ||||
| input.Key = destKeyName | input.Key = destKeyName | ||||
| @@ -529,11 +526,12 @@ func GetObsListObject(jobName, outPutPath, parentDir, versionName string) ([]Fil | |||||
| } | } | ||||
| } | } | ||||
| func ObsGenMultiPartSignedUrl(uuid string, uploadId string, partNumber int, fileName string) (string, error) { | |||||
| func ObsGenMultiPartSignedUrl(objectName string, uploadId string, partNumber int) (string, error) { | |||||
| input := &obs.CreateSignedUrlInput{} | input := &obs.CreateSignedUrlInput{} | ||||
| input.Bucket = setting.Bucket | input.Bucket = setting.Bucket | ||||
| input.Key = strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| input.Key = objectName | |||||
| //strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| input.Expires = 60 * 60 | input.Expires = 60 * 60 | ||||
| input.Method = obs.HttpMethodPut | input.Method = obs.HttpMethodPut | ||||
| @@ -581,10 +579,11 @@ func GetObsCreateSignedUrl(jobName, parentDir, fileName string) (string, error) | |||||
| return GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir, fileName), "/")) | return GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir, fileName), "/")) | ||||
| } | } | ||||
| func ObsGetPreSignedUrl(uuid, fileName string) (string, error) { | |||||
| func ObsGetPreSignedUrl(objectName, fileName string) (string, error) { | |||||
| input := &obs.CreateSignedUrlInput{} | input := &obs.CreateSignedUrlInput{} | ||||
| input.Method = obs.HttpMethodGet | input.Method = obs.HttpMethodGet | ||||
| input.Key = strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| input.Key = objectName | |||||
| //strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| input.Bucket = setting.Bucket | input.Bucket = setting.Bucket | ||||
| input.Expires = 60 * 60 | input.Expires = 60 * 60 | ||||
| @@ -1273,12 +1273,14 @@ model.manage.model_accuracy = Model Accuracy | |||||
| model.convert=Model Transformation | model.convert=Model Transformation | ||||
| model.list=Model List | model.list=Model List | ||||
| model.manage.create_new_convert_task=Create Model Transformation Task | model.manage.create_new_convert_task=Create Model Transformation Task | ||||
| model.manage.import_local_model=Import Local Model | |||||
| model.manage.import_online_model=Import Online Model | |||||
| model.manage.notcreatemodel=No model has been created | model.manage.notcreatemodel=No model has been created | ||||
| model.manage.init1=Code version: You have not initialized the code repository, please | model.manage.init1=Code version: You have not initialized the code repository, please | ||||
| model.manage.init2=initialized first ; | model.manage.init2=initialized first ; | ||||
| model.manage.createtrainjob_tip=Training task: you haven't created a training task, please create it first | model.manage.createtrainjob_tip=Training task: you haven't created a training task, please create it first | ||||
| model.manage.createtrainjob=Training task. | |||||
| model.manage.createmodel_tip=You can import local model or online model. Import online model should | |||||
| model.manage.createtrainjob=Create training task. | |||||
| model.manage.delete=Delete Model | model.manage.delete=Delete Model | ||||
| model.manage.delete_confirm=Are you sure to delete this model? Once this model is deleted, it cannot be restored. | model.manage.delete_confirm=Are you sure to delete this model? Once this model is deleted, it cannot be restored. | ||||
| model.manage.select.trainjob=Select train task | model.manage.select.trainjob=Select train task | ||||
| @@ -1287,12 +1287,14 @@ model.manage.model_accuracy = 模型精度 | |||||
| model.convert=模型转换任务 | model.convert=模型转换任务 | ||||
| model.list=模型列表 | model.list=模型列表 | ||||
| model.manage.create_new_convert_task=创建模型转换任务 | model.manage.create_new_convert_task=创建模型转换任务 | ||||
| model.manage.import_local_model=导入本地模型 | |||||
| model.manage.import_online_model=导入线上模型 | |||||
| model.manage.notcreatemodel=未创建过模型 | model.manage.notcreatemodel=未创建过模型 | ||||
| model.manage.init1=代码版本:您还没有初始化代码仓库,请先 | model.manage.init1=代码版本:您还没有初始化代码仓库,请先 | ||||
| model.manage.init2=创建代码版本; | model.manage.init2=创建代码版本; | ||||
| model.manage.createtrainjob_tip=训练任务:您还没创建过训练任务,请先创建 | model.manage.createtrainjob_tip=训练任务:您还没创建过训练任务,请先创建 | ||||
| model.manage.createtrainjob=训练任务。 | |||||
| model.manage.createmodel_tip=您可以导入本地模型或者导入线上模型。导入线上模型需先 | |||||
| model.manage.createtrainjob=创建训练任务。 | |||||
| model.manage.delete=删除模型 | model.manage.delete=删除模型 | ||||
| model.manage.delete_confirm=你确认删除该模型么?此模型一旦删除不可恢复。 | model.manage.delete_confirm=你确认删除该模型么?此模型一旦删除不可恢复。 | ||||
| model.manage.select.trainjob=选择训练任务 | model.manage.select.trainjob=选择训练任务 | ||||
| @@ -17,6 +17,7 @@ import ( | |||||
| "code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||||
| ) | ) | ||||
| const ( | const ( | ||||
| @@ -95,6 +96,8 @@ func CloudBrains(ctx *context.Context) { | |||||
| models.LoadSpecs4CloudbrainInfo(ciTasks) | models.LoadSpecs4CloudbrainInfo(ciTasks) | ||||
| for i, task := range ciTasks { | for i, task := range ciTasks { | ||||
| ciTasks[i] = cloudbrainService.UpdateCloudbrainAiCenter(ciTasks[i]) | |||||
| ciTasks[i].Cloudbrain.AiCenter = repo.GetAiCenterNameByCode(ciTasks[i].Cloudbrain.AiCenter, ctx.Language()) | |||||
| ciTasks[i].CanDebug = true | ciTasks[i].CanDebug = true | ||||
| ciTasks[i].CanDel = true | ciTasks[i].CanDel = true | ||||
| ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource | ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource | ||||
| @@ -186,7 +189,8 @@ func DownloadCloudBrains(ctx *context.Context) { | |||||
| } | } | ||||
| models.LoadSpecs4CloudbrainInfo(pageRecords) | models.LoadSpecs4CloudbrainInfo(pageRecords) | ||||
| for _, record := range pageRecords { | for _, record := range pageRecords { | ||||
| record = cloudbrainService.UpdateCloudbrainAiCenter(record) | |||||
| record.Cloudbrain.AiCenter = repo.GetAiCenterNameByCode(record.Cloudbrain.AiCenter, ctx.Language()) | |||||
| for k, v := range allValues(row, record, ctx) { | for k, v := range allValues(row, record, ctx) { | ||||
| f.SetCellValue(cloudBrain, k, v) | f.SetCellValue(cloudBrain, k, v) | ||||
| } | } | ||||
| @@ -208,7 +212,7 @@ func allValues(row int, rs *models.CloudbrainInfo, ctx *context.Context) map[str | |||||
| return map[string]string{getCellName("A", row): rs.DisplayJobName, getCellName("B", row): repo.GetCloudbrainCluster(rs.Cloudbrain, ctx), | return map[string]string{getCellName("A", row): rs.DisplayJobName, getCellName("B", row): repo.GetCloudbrainCluster(rs.Cloudbrain, ctx), | ||||
| getCellName("C", row): rs.JobType, getCellName("D", row): rs.Status, getCellName("E", row): time.Unix(int64(rs.Cloudbrain.CreatedUnix), 0).Format(CREATE_TIME_FORMAT), | getCellName("C", row): rs.JobType, getCellName("D", row): rs.Status, getCellName("E", row): time.Unix(int64(rs.Cloudbrain.CreatedUnix), 0).Format(CREATE_TIME_FORMAT), | ||||
| getCellName("F", row): getDurationTime(rs), getCellName("G", row): rs.ComputeResource, | getCellName("F", row): getDurationTime(rs), getCellName("G", row): rs.ComputeResource, | ||||
| getCellName("H", row): repo.GetCloudbrainAiCenter(rs.Cloudbrain, ctx), getCellName("I", row): getCloudbrainCardType(rs), | |||||
| getCellName("H", row): rs.Cloudbrain.AiCenter, getCellName("I", row): getCloudbrainCardType(rs), | |||||
| getCellName("J", row): rs.Name, getCellName("K", row): getRepoPathName(rs), getCellName("L", row): rs.JobName, | getCellName("J", row): rs.Name, getCellName("K", row): getRepoPathName(rs), getCellName("L", row): rs.JobName, | ||||
| } | } | ||||
| } | } | ||||
| @@ -127,6 +127,7 @@ func GetResourceSpecificationList(ctx *context.Context) { | |||||
| Status: status, | Status: status, | ||||
| Cluster: cluster, | Cluster: cluster, | ||||
| AvailableCode: available, | AvailableCode: available, | ||||
| OrderBy: models.SearchSpecOrderById, | |||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("GetResourceSpecificationList error.%v", err) | log.Error("GetResourceSpecificationList error.%v", err) | ||||
| @@ -136,6 +137,26 @@ func GetResourceSpecificationList(ctx *context.Context) { | |||||
| ctx.JSON(http.StatusOK, response.SuccessWithData(list)) | ctx.JSON(http.StatusOK, response.SuccessWithData(list)) | ||||
| } | } | ||||
| func GetAllResourceSpecificationList(ctx *context.Context) { | |||||
| queue := ctx.QueryInt64("queue") | |||||
| status := ctx.QueryInt("status") | |||||
| cluster := ctx.Query("cluster") | |||||
| available := ctx.QueryInt("available") | |||||
| list, err := resource.GetAllDistinctResourceSpecification(models.SearchResourceSpecificationOptions{ | |||||
| QueueId: queue, | |||||
| Status: status, | |||||
| Cluster: cluster, | |||||
| AvailableCode: available, | |||||
| }) | |||||
| if err != nil { | |||||
| log.Error("GetResourceSpecificationList error.%v", err) | |||||
| ctx.JSON(http.StatusOK, response.ServerError(err.Error())) | |||||
| return | |||||
| } | |||||
| ctx.JSON(http.StatusOK, response.SuccessWithData(list)) | |||||
| } | |||||
| func GetResourceSpecificationScenes(ctx *context.Context) { | func GetResourceSpecificationScenes(ctx *context.Context) { | ||||
| specId := ctx.ParamsInt64(":id") | specId := ctx.ParamsInt64(":id") | ||||
| list, err := resource.GetResourceSpecificationScenes(specId) | list, err := resource.GetResourceSpecificationScenes(specId) | ||||
| @@ -631,6 +631,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Get("/overview_resource", repo.GetCloudbrainResourceOverview) | m.Get("/overview_resource", repo.GetCloudbrainResourceOverview) | ||||
| m.Get("/resource_usage_statistic", repo.GetDurationRateStatistic) | m.Get("/resource_usage_statistic", repo.GetDurationRateStatistic) | ||||
| m.Get("/resource_usage_rate_detail", repo.GetCloudbrainResourceUsageDetail) | m.Get("/resource_usage_rate_detail", repo.GetCloudbrainResourceUsageDetail) | ||||
| m.Get("/resource_queues", repo.GetResourceQueues) | |||||
| m.Get("/apitest_for_statistic", repo.CloudbrainDurationStatisticForTest) | m.Get("/apitest_for_statistic", repo.CloudbrainDurationStatisticForTest) | ||||
| }) | }) | ||||
| }, operationReq) | }, operationReq) | ||||
| @@ -1017,7 +1018,9 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Get("/query_modelfile_for_predict", repo.QueryModelFileForPredict) | m.Get("/query_modelfile_for_predict", repo.QueryModelFileForPredict) | ||||
| m.Get("/query_train_model", repo.QueryTrainModelList) | m.Get("/query_train_model", repo.QueryTrainModelList) | ||||
| m.Post("/create_model_convert", repo.CreateModelConvert) | m.Post("/create_model_convert", repo.CreateModelConvert) | ||||
| m.Get("/show_model_convert_page") | |||||
| m.Get("/show_model_convert_page", repo.ShowModelConvertPage) | |||||
| m.Get("/query_model_convert_byId", repo.QueryModelConvertById) | |||||
| m.Get("/:id", repo.GetCloudbrainModelConvertTask) | m.Get("/:id", repo.GetCloudbrainModelConvertTask) | ||||
| m.Get("/:id/log", repo.CloudbrainForModelConvertGetLog) | m.Get("/:id/log", repo.CloudbrainForModelConvertGetLog) | ||||
| m.Get("/:id/modelartlog", repo.TrainJobForModelConvertGetLog) | m.Get("/:id/modelartlog", repo.TrainJobForModelConvertGetLog) | ||||
| @@ -1054,6 +1057,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Get("", repo.GetModelArtsTrainJobVersion) | m.Get("", repo.GetModelArtsTrainJobVersion) | ||||
| m.Post("/stop_version", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo_ext.GrampusStopJob) | m.Post("/stop_version", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo_ext.GrampusStopJob) | ||||
| m.Get("/log", repo_ext.GrampusGetLog) | m.Get("/log", repo_ext.GrampusGetLog) | ||||
| m.Get("/metrics", repo_ext.GrampusMetrics) | |||||
| m.Get("/download_log", cloudbrain.AdminOrJobCreaterRightForTrain, repo_ext.GrampusDownloadLog) | m.Get("/download_log", cloudbrain.AdminOrJobCreaterRightForTrain, repo_ext.GrampusDownloadLog) | ||||
| }) | }) | ||||
| }) | }) | ||||
| @@ -666,12 +666,24 @@ func CloudbrainGetLog(ctx *context.APIContext) { | |||||
| existStr = taskRes.TaskStatuses[0].ExitDiagnostics | existStr = taskRes.TaskStatuses[0].ExitDiagnostics | ||||
| } | } | ||||
| ctx.Data["existStr"] = existStr | ctx.Data["existStr"] = existStr | ||||
| log.Info("existStr=" + existStr) | |||||
| } else { | } else { | ||||
| ModelSafetyGetLog(ctx) | ModelSafetyGetLog(ctx) | ||||
| return | return | ||||
| } | } | ||||
| } | |||||
| if job.JobType == string(models.JobTypeTrain) || job.JobType == string(models.JobTypeInference) { | |||||
| if job.Type == models.TypeCloudBrainOne { | |||||
| result, err := cloudbrain.GetJob(job.JobID) | |||||
| existStr := "" | |||||
| if err == nil && result != nil { | |||||
| jobRes, _ := models.ConvertToJobResultPayload(result.Payload) | |||||
| taskRoles := jobRes.TaskRoles | |||||
| taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||||
| existStr = taskRes.TaskStatuses[0].ExitDiagnostics | |||||
| } | |||||
| ctx.Data["existStr"] = existStr | |||||
| } | |||||
| } | } | ||||
| lines := ctx.QueryInt("lines") | lines := ctx.QueryInt("lines") | ||||
| @@ -716,17 +728,25 @@ func CloudbrainGetLog(ctx *context.APIContext) { | |||||
| if result["Content"] != nil { | if result["Content"] != nil { | ||||
| content = result["Content"].(string) | content = result["Content"].(string) | ||||
| } | } | ||||
| if ctx.Data["existStr"] != nil && result["Lines"].(int) < 50 { | if ctx.Data["existStr"] != nil && result["Lines"].(int) < 50 { | ||||
| content = content + ctx.Data["existStr"].(string) | content = content + ctx.Data["existStr"].(string) | ||||
| } | } | ||||
| logFileName := result["FileName"] | |||||
| //Logs can only be downloaded if the file exists | |||||
| //and the current user is an administrator or the creator of the task | |||||
| canLogDownload := logFileName != nil && logFileName != "" && job.IsUserHasRight(ctx.User) | |||||
| re := map[string]interface{}{ | re := map[string]interface{}{ | ||||
| "JobID": ID, | "JobID": ID, | ||||
| "LogFileName": result["FileName"], | |||||
| "LogFileName": logFileName, | |||||
| "StartLine": result["StartLine"], | "StartLine": result["StartLine"], | ||||
| "EndLine": result["EndLine"], | "EndLine": result["EndLine"], | ||||
| "Content": content, | "Content": content, | ||||
| "Lines": result["Lines"], | "Lines": result["Lines"], | ||||
| "CanLogDownload": result["FileName"] != "", | |||||
| "CanLogDownload": canLogDownload, | |||||
| "StartTime": job.StartTime, | "StartTime": job.StartTime, | ||||
| } | } | ||||
| //result := CloudbrainGetLogByJobId(job.JobID, job.JobName) | //result := CloudbrainGetLogByJobId(job.JobID, job.JobName) | ||||
| @@ -12,6 +12,8 @@ import ( | |||||
| "code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| "code.gitea.io/gitea/routers/repo" | "code.gitea.io/gitea/routers/repo" | ||||
| cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||||
| "code.gitea.io/gitea/services/cloudbrain/resource" | |||||
| "github.com/360EntSecGroup-Skylar/excelize/v2" | "github.com/360EntSecGroup-Skylar/excelize/v2" | ||||
| ) | ) | ||||
| @@ -121,8 +123,8 @@ func GetOverviewDuration(ctx *context.Context) { | |||||
| recordBeginTime := recordCloudbrain[0].Cloudbrain.CreatedUnix | recordBeginTime := recordCloudbrain[0].Cloudbrain.CreatedUnix | ||||
| now := time.Now() | now := time.Now() | ||||
| endTime := now | endTime := now | ||||
| worker_server_num := 1 | |||||
| cardNum := 1 | |||||
| // worker_server_num := 1 | |||||
| // cardNum := 1 | |||||
| durationAllSum := int64(0) | durationAllSum := int64(0) | ||||
| cardDuSum := int64(0) | cardDuSum := int64(0) | ||||
| @@ -148,34 +150,40 @@ func GetOverviewDuration(ctx *context.Context) { | |||||
| models.LoadSpecs4CloudbrainInfo(cloudbrains) | models.LoadSpecs4CloudbrainInfo(cloudbrains) | ||||
| for _, cloudbrain := range 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) | |||||
| cloudbrain = cloudbrainService.UpdateCloudbrainAiCenter(cloudbrain) | |||||
| CardDurationString := repo.GetCloudbrainCardDuration(cloudbrain.Cloudbrain) | |||||
| CardDuration := models.ConvertStrToDuration(CardDurationString) | |||||
| // 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 | |||||
| // duration := cloudbrain.Duration | |||||
| duration := models.ConvertStrToDuration(cloudbrain.TrainJobDuration) | |||||
| // CardDuration := cloudbrain.Duration * int64(worker_server_num) * int64(cardNum) | |||||
| if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainOne { | if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainOne { | ||||
| cloudBrainOneDuration += duration | cloudBrainOneDuration += duration | ||||
| cloudBrainOneCardDuSum += durationSum | |||||
| cloudBrainOneCardDuSum += CardDuration | |||||
| } else if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainTwo { | } else if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainTwo { | ||||
| cloudBrainTwoDuration += duration | cloudBrainTwoDuration += duration | ||||
| cloudBrainTwoCardDuSum += durationSum | |||||
| cloudBrainTwoCardDuSum += CardDuration | |||||
| } else if cloudbrain.Cloudbrain.Type == models.TypeC2Net { | } else if cloudbrain.Cloudbrain.Type == models.TypeC2Net { | ||||
| c2NetDuration += duration | c2NetDuration += duration | ||||
| c2NetCardDuSum += durationSum | |||||
| c2NetCardDuSum += CardDuration | |||||
| } else if cloudbrain.Cloudbrain.Type == models.TypeCDCenter { | } else if cloudbrain.Cloudbrain.Type == models.TypeCDCenter { | ||||
| cDCenterDuration += duration | cDCenterDuration += duration | ||||
| cDNetCardDuSum += durationSum | |||||
| cDNetCardDuSum += CardDuration | |||||
| } | } | ||||
| durationAllSum += duration | durationAllSum += duration | ||||
| cardDuSum += durationSum | |||||
| cardDuSum += CardDuration | |||||
| } | } | ||||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | ctx.JSON(http.StatusOK, map[string]interface{}{ | ||||
| "cloudBrainOneCardDuSum": cloudBrainOneCardDuSum, | "cloudBrainOneCardDuSum": cloudBrainOneCardDuSum, | ||||
| @@ -192,6 +200,28 @@ func GetOverviewDuration(ctx *context.Context) { | |||||
| }) | }) | ||||
| } | } | ||||
| func GetCloudbrainCardDuration(task models.Cloudbrain) string { | |||||
| cardNum := int(0) | |||||
| spec, err := resource.GetCloudbrainSpec(task.ID) | |||||
| if err != nil { | |||||
| log.Info("error:" + err.Error()) | |||||
| return "" | |||||
| } | |||||
| if spec != nil { | |||||
| cardNum = spec.AccCardsNum | |||||
| } else { | |||||
| cardNum = 1 | |||||
| } | |||||
| var workServerNumber int64 | |||||
| if task.WorkServerNumber >= 1 { | |||||
| workServerNumber = int64(task.WorkServerNumber) | |||||
| } else { | |||||
| workServerNumber = 1 | |||||
| } | |||||
| cardDuration := models.ConvertDurationToStr(workServerNumber * int64(cardNum) * task.Duration) | |||||
| return cardDuration | |||||
| } | |||||
| func GetAllCloudbrainsTrend(ctx *context.Context) { | func GetAllCloudbrainsTrend(ctx *context.Context) { | ||||
| queryType := ctx.QueryTrim("type") | queryType := ctx.QueryTrim("type") | ||||
| @@ -703,6 +733,30 @@ func GetCloudbrainsDetailData(ctx *context.Context) { | |||||
| aiCenter := ctx.Query("aiCenter") | aiCenter := ctx.Query("aiCenter") | ||||
| needDeleteInfo := ctx.Query("needDeleteInfo") | needDeleteInfo := ctx.Query("needDeleteInfo") | ||||
| if cloudBrainType == models.TypeCloudBrainOne && aiCenter == models.AICenterOfCloudBrainOne { | |||||
| aiCenter = "" | |||||
| } | |||||
| if cloudBrainType == models.TypeCloudBrainTwo && aiCenter == models.AICenterOfCloudBrainTwo { | |||||
| aiCenter = "" | |||||
| } | |||||
| if cloudBrainType == models.TypeCDCenter && aiCenter == models.AICenterOfChengdu { | |||||
| aiCenter = "" | |||||
| } | |||||
| if cloudBrainType == models.TypeCloudBrainAll { | |||||
| if aiCenter == models.AICenterOfCloudBrainOne { | |||||
| cloudBrainType = models.TypeCloudBrainOne | |||||
| aiCenter = "" | |||||
| } | |||||
| if aiCenter == models.AICenterOfCloudBrainTwo { | |||||
| cloudBrainType = models.TypeCloudBrainTwo | |||||
| aiCenter = "" | |||||
| } | |||||
| if aiCenter == models.AICenterOfChengdu { | |||||
| cloudBrainType = models.TypeCDCenter | |||||
| aiCenter = "" | |||||
| } | |||||
| } | |||||
| page := ctx.QueryInt("page") | page := ctx.QueryInt("page") | ||||
| pageSize := ctx.QueryInt("pagesize") | pageSize := ctx.QueryInt("pagesize") | ||||
| if page <= 0 { | if page <= 0 { | ||||
| @@ -732,7 +786,7 @@ func GetCloudbrainsDetailData(ctx *context.Context) { | |||||
| keyword := strings.Trim(ctx.Query("q"), " ") | keyword := strings.Trim(ctx.Query("q"), " ") | ||||
| ciTasks, _, err := models.CloudbrainAll(&models.CloudbrainsOptions{ | |||||
| ciTasks, count, err := models.CloudbrainAll(&models.CloudbrainsOptions{ | |||||
| ListOptions: models.ListOptions{ | ListOptions: models.ListOptions{ | ||||
| Page: page, | Page: page, | ||||
| PageSize: pageSize, | PageSize: pageSize, | ||||
| @@ -747,8 +801,8 @@ func GetCloudbrainsDetailData(ctx *context.Context) { | |||||
| NeedRepoInfo: true, | NeedRepoInfo: true, | ||||
| BeginTimeUnix: int64(recordBeginTime), | BeginTimeUnix: int64(recordBeginTime), | ||||
| EndTimeUnix: endTime.Unix(), | EndTimeUnix: endTime.Unix(), | ||||
| // AiCenter: aiCenter, | |||||
| NeedDeleteInfo: needDeleteInfo, | |||||
| AiCenter: aiCenter, | |||||
| NeedDeleteInfo: needDeleteInfo, | |||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| ctx.ServerError("Get job failed:", err) | ctx.ServerError("Get job failed:", err) | ||||
| @@ -758,45 +812,43 @@ func GetCloudbrainsDetailData(ctx *context.Context) { | |||||
| nilTime := time.Time{} | nilTime := time.Time{} | ||||
| tasks := []models.TaskDetail{} | tasks := []models.TaskDetail{} | ||||
| for i, task := range ciTasks { | for i, task := range ciTasks { | ||||
| if aiCenter == "" || aiCenter == task.Cloudbrain.Spec.AiCenterCode { | |||||
| ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource | |||||
| var taskDetail models.TaskDetail | |||||
| taskDetail.ID = ciTasks[i].Cloudbrain.ID | |||||
| taskDetail.JobID = ciTasks[i].Cloudbrain.JobID | |||||
| taskDetail.JobName = ciTasks[i].JobName | |||||
| taskDetail.DisplayJobName = ciTasks[i].DisplayJobName | |||||
| taskDetail.Status = ciTasks[i].Status | |||||
| taskDetail.JobType = ciTasks[i].JobType | |||||
| taskDetail.CreatedUnix = ciTasks[i].Cloudbrain.CreatedUnix | |||||
| taskDetail.RunTime = ciTasks[i].Cloudbrain.TrainJobDuration | |||||
| taskDetail.StartTime = ciTasks[i].StartTime | |||||
| taskDetail.EndTime = ciTasks[i].EndTime | |||||
| taskDetail.ComputeResource = ciTasks[i].ComputeResource | |||||
| taskDetail.Type = ciTasks[i].Cloudbrain.Type | |||||
| taskDetail.UserName = ciTasks[i].User.Name | |||||
| taskDetail.RepoID = ciTasks[i].RepoID | |||||
| if ciTasks[i].Repo != nil { | |||||
| taskDetail.RepoName = ciTasks[i].Repo.OwnerName + "/" + ciTasks[i].Repo.Name | |||||
| taskDetail.RepoAlias = ciTasks[i].Repo.OwnerName + "/" + ciTasks[i].Repo.Alias | |||||
| } | |||||
| if ciTasks[i].Cloudbrain.WorkServerNumber >= 1 { | |||||
| taskDetail.WorkServerNum = int64(ciTasks[i].Cloudbrain.WorkServerNumber) | |||||
| } else { | |||||
| taskDetail.WorkServerNum = 1 | |||||
| } | |||||
| taskDetail.CardDuration = repo.GetCloudbrainCardDuration(ciTasks[i].Cloudbrain) | |||||
| taskDetail.WaitTime = repo.GetCloudbrainWaitTime(ciTasks[i].Cloudbrain) | |||||
| task = cloudbrainService.UpdateCloudbrainAiCenter(task) | |||||
| var taskDetail models.TaskDetail | |||||
| taskDetail.ID = ciTasks[i].Cloudbrain.ID | |||||
| taskDetail.JobID = ciTasks[i].Cloudbrain.JobID | |||||
| taskDetail.JobName = ciTasks[i].JobName | |||||
| taskDetail.DisplayJobName = ciTasks[i].DisplayJobName | |||||
| taskDetail.Status = ciTasks[i].Status | |||||
| taskDetail.JobType = ciTasks[i].JobType | |||||
| taskDetail.CreatedUnix = ciTasks[i].Cloudbrain.CreatedUnix | |||||
| taskDetail.RunTime = ciTasks[i].Cloudbrain.TrainJobDuration | |||||
| taskDetail.StartTime = ciTasks[i].StartTime | |||||
| taskDetail.EndTime = ciTasks[i].EndTime | |||||
| taskDetail.ComputeResource = ciTasks[i].ComputeResource | |||||
| taskDetail.Type = ciTasks[i].Cloudbrain.Type | |||||
| taskDetail.UserName = ciTasks[i].User.Name | |||||
| taskDetail.RepoID = ciTasks[i].RepoID | |||||
| taskDetail.AiCenter = repo.GetAiCenterNameByCode(task.Cloudbrain.AiCenter, ctx.Language()) | |||||
| if ciTasks[i].Repo != nil { | |||||
| taskDetail.RepoName = ciTasks[i].Repo.OwnerName + "/" + ciTasks[i].Repo.Name | |||||
| taskDetail.RepoAlias = ciTasks[i].Repo.OwnerName + "/" + ciTasks[i].Repo.Alias | |||||
| } | |||||
| if ciTasks[i].Cloudbrain.WorkServerNumber >= 1 { | |||||
| taskDetail.WorkServerNum = int64(ciTasks[i].Cloudbrain.WorkServerNumber) | |||||
| } else { | |||||
| taskDetail.WorkServerNum = 1 | |||||
| } | |||||
| taskDetail.CardDuration = repo.GetCloudbrainCardDuration(ciTasks[i].Cloudbrain) | |||||
| taskDetail.WaitTime = repo.GetCloudbrainWaitTime(ciTasks[i].Cloudbrain) | |||||
| if ciTasks[i].Cloudbrain.DeletedAt != nilTime || ciTasks[i].Repo == nil { | |||||
| taskDetail.IsDelete = true | |||||
| } else { | |||||
| taskDetail.IsDelete = false | |||||
| } | |||||
| taskDetail.Spec = ciTasks[i].Spec | |||||
| tasks = append(tasks, taskDetail) | |||||
| if ciTasks[i].Cloudbrain.DeletedAt != nilTime || ciTasks[i].Repo == nil { | |||||
| taskDetail.IsDelete = true | |||||
| } else { | |||||
| taskDetail.IsDelete = false | |||||
| } | } | ||||
| taskDetail.Spec = ciTasks[i].Spec | |||||
| tasks = append(tasks, taskDetail) | |||||
| } | } | ||||
| count := int64(len(tasks)) | |||||
| pager := context.NewPagination(int(count), pageSize, page, getTotalPage(count, pageSize)) | pager := context.NewPagination(int(count), pageSize, page, getTotalPage(count, pageSize)) | ||||
| pager.SetDefaultParams(ctx) | pager.SetDefaultParams(ctx) | ||||
| pager.AddParam(ctx, "listType", "ListType") | pager.AddParam(ctx, "listType", "ListType") | ||||
| @@ -1176,6 +1228,12 @@ func getMonthCloudbrainInfo(beginTime time.Time, endTime time.Time) ([]DateCloud | |||||
| } | } | ||||
| func DownloadCloudBrainBoard(ctx *context.Context) { | func DownloadCloudBrainBoard(ctx *context.Context) { | ||||
| recordCloudbrain, err := models.GetRecordBeginTime() | |||||
| if err != nil { | |||||
| log.Error("Can not get recordCloudbrain", err) | |||||
| ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) | |||||
| return | |||||
| } | |||||
| page := 1 | page := 1 | ||||
| @@ -1184,14 +1242,20 @@ func DownloadCloudBrainBoard(ctx *context.Context) { | |||||
| var cloudBrain = ctx.Tr("repo.cloudbrain") | var cloudBrain = ctx.Tr("repo.cloudbrain") | ||||
| fileName := getCloudbrainFileName(cloudBrain) | fileName := getCloudbrainFileName(cloudBrain) | ||||
| recordBeginTime := recordCloudbrain[0].Cloudbrain.CreatedUnix | |||||
| now := time.Now() | |||||
| endTime := now | |||||
| _, total, err := models.CloudbrainAll(&models.CloudbrainsOptions{ | _, total, err := models.CloudbrainAll(&models.CloudbrainsOptions{ | ||||
| ListOptions: models.ListOptions{ | ListOptions: models.ListOptions{ | ||||
| Page: page, | Page: page, | ||||
| PageSize: pageSize, | PageSize: pageSize, | ||||
| }, | }, | ||||
| Type: models.TypeCloudBrainAll, | |||||
| NeedRepoInfo: false, | |||||
| Type: models.TypeCloudBrainAll, | |||||
| BeginTimeUnix: int64(recordBeginTime), | |||||
| EndTimeUnix: endTime.Unix(), | |||||
| }) | }) | ||||
| log.Info("totalcountisis:", total) | |||||
| if err != nil { | if err != nil { | ||||
| log.Warn("Can not get cloud brain info", err) | log.Warn("Can not get cloud brain info", err) | ||||
| @@ -1216,8 +1280,10 @@ func DownloadCloudBrainBoard(ctx *context.Context) { | |||||
| Page: page, | Page: page, | ||||
| PageSize: pageSize, | PageSize: pageSize, | ||||
| }, | }, | ||||
| Type: models.TypeCloudBrainAll, | |||||
| NeedRepoInfo: true, | |||||
| Type: models.TypeCloudBrainAll, | |||||
| BeginTimeUnix: int64(recordBeginTime), | |||||
| EndTimeUnix: endTime.Unix(), | |||||
| NeedRepoInfo: true, | |||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| log.Warn("Can not get cloud brain info", err) | log.Warn("Can not get cloud brain info", err) | ||||
| @@ -1225,7 +1291,8 @@ func DownloadCloudBrainBoard(ctx *context.Context) { | |||||
| } | } | ||||
| models.LoadSpecs4CloudbrainInfo(pageRecords) | models.LoadSpecs4CloudbrainInfo(pageRecords) | ||||
| for _, record := range pageRecords { | for _, record := range pageRecords { | ||||
| record = cloudbrainService.UpdateCloudbrainAiCenter(record) | |||||
| record.Cloudbrain.AiCenter = repo.GetAiCenterNameByCode(record.Cloudbrain.AiCenter, ctx.Language()) | |||||
| for k, v := range allCloudbrainValues(row, record, ctx) { | for k, v := range allCloudbrainValues(row, record, ctx) { | ||||
| f.SetCellValue(cloudBrain, k, v) | f.SetCellValue(cloudBrain, k, v) | ||||
| } | } | ||||
| @@ -1264,7 +1331,7 @@ func allCloudbrainValues(row int, rs *models.CloudbrainInfo, ctx *context.Contex | |||||
| getCellName("G", row): rs.TrainJobDuration, getCellName("H", row): repo.GetCloudbrainCardDuration(rs.Cloudbrain), | getCellName("G", row): rs.TrainJobDuration, getCellName("H", row): repo.GetCloudbrainCardDuration(rs.Cloudbrain), | ||||
| getCellName("I", row): getBrainStartTime(rs), | getCellName("I", row): getBrainStartTime(rs), | ||||
| getCellName("J", row): getBrainEndTime(rs), getCellName("K", row): rs.ComputeResource, getCellName("L", row): getCloudbrainCardType(rs), | getCellName("J", row): getBrainEndTime(rs), getCellName("K", row): rs.ComputeResource, getCellName("L", row): getCloudbrainCardType(rs), | ||||
| getCellName("M", row): getWorkServerNum(rs), getCellName("N", row): repo.GetCloudbrainAiCenter(rs.Cloudbrain, ctx), | |||||
| getCellName("M", row): getWorkServerNum(rs), getCellName("N", row): rs.Cloudbrain.AiCenter, | |||||
| getCellName("O", row): getCloudbrainFlavorName(rs), getCellName("P", row): rs.Name, | getCellName("O", row): getCloudbrainFlavorName(rs), getCellName("P", row): rs.Name, | ||||
| getCellName("Q", row): getBrainRepo(rs), getCellName("R", row): rs.JobName, getCellName("S", row): getBrainDeleteTime(rs), | getCellName("Q", row): getBrainRepo(rs), getCellName("R", row): rs.JobName, getCellName("S", row): getBrainDeleteTime(rs), | ||||
| } | } | ||||
| @@ -1417,7 +1484,7 @@ func GetCloudbrainResourceOverview(ctx *context.Context) { | |||||
| log.Error("Can not get GetDurationRecordBeginTime", err) | log.Error("Can not get GetDurationRecordBeginTime", err) | ||||
| return | return | ||||
| } | } | ||||
| recordBeginTime := recordCloudbrainDuration[0].CreatedUnix | |||||
| recordBeginTime := recordCloudbrainDuration[0].DateTime | |||||
| recordUpdateTime := time.Now().Unix() | recordUpdateTime := time.Now().Unix() | ||||
| resourceQueues, err := models.GetCanUseCardInfo() | resourceQueues, err := models.GetCanUseCardInfo() | ||||
| if err != nil { | if err != nil { | ||||
| @@ -1428,11 +1495,12 @@ func GetCloudbrainResourceOverview(ctx *context.Context) { | |||||
| C2NetResourceDetail := []models.ResourceDetail{} | C2NetResourceDetail := []models.ResourceDetail{} | ||||
| for _, resourceQueue := range resourceQueues { | for _, resourceQueue := range resourceQueues { | ||||
| if resourceQueue.Cluster == models.OpenICluster { | if resourceQueue.Cluster == models.OpenICluster { | ||||
| aiCenterName := repo.GetAiCenterNameByCode(resourceQueue.AiCenterCode, ctx.Language()) | |||||
| var resourceDetail models.ResourceDetail | var resourceDetail models.ResourceDetail | ||||
| resourceDetail.QueueCode = resourceQueue.QueueCode | resourceDetail.QueueCode = resourceQueue.QueueCode | ||||
| resourceDetail.Cluster = resourceQueue.Cluster | resourceDetail.Cluster = resourceQueue.Cluster | ||||
| resourceDetail.AiCenterCode = resourceQueue.AiCenterCode | resourceDetail.AiCenterCode = resourceQueue.AiCenterCode | ||||
| resourceDetail.AiCenterName = resourceQueue.AiCenterName + "/" + resourceQueue.AiCenterCode | |||||
| resourceDetail.AiCenterName = resourceQueue.AiCenterCode + "/" + aiCenterName | |||||
| resourceDetail.ComputeResource = resourceQueue.ComputeResource | resourceDetail.ComputeResource = resourceQueue.ComputeResource | ||||
| resourceDetail.AccCardType = resourceQueue.AccCardType + "(" + resourceQueue.ComputeResource + ")" | resourceDetail.AccCardType = resourceQueue.AccCardType + "(" + resourceQueue.ComputeResource + ")" | ||||
| resourceDetail.CardsTotalNum = resourceQueue.CardsTotalNum | resourceDetail.CardsTotalNum = resourceQueue.CardsTotalNum | ||||
| @@ -1440,11 +1508,12 @@ func GetCloudbrainResourceOverview(ctx *context.Context) { | |||||
| OpenIResourceDetail = append(OpenIResourceDetail, resourceDetail) | OpenIResourceDetail = append(OpenIResourceDetail, resourceDetail) | ||||
| } | } | ||||
| if resourceQueue.Cluster == models.C2NetCluster { | if resourceQueue.Cluster == models.C2NetCluster { | ||||
| aiCenterName := repo.GetAiCenterNameByCode(resourceQueue.AiCenterCode, ctx.Language()) | |||||
| var resourceDetail models.ResourceDetail | var resourceDetail models.ResourceDetail | ||||
| resourceDetail.QueueCode = resourceQueue.QueueCode | resourceDetail.QueueCode = resourceQueue.QueueCode | ||||
| resourceDetail.Cluster = resourceQueue.Cluster | resourceDetail.Cluster = resourceQueue.Cluster | ||||
| resourceDetail.AiCenterCode = resourceQueue.AiCenterCode | resourceDetail.AiCenterCode = resourceQueue.AiCenterCode | ||||
| resourceDetail.AiCenterName = resourceQueue.AiCenterName + "/" + resourceQueue.AiCenterCode | |||||
| resourceDetail.AiCenterName = resourceQueue.AiCenterCode + "/" + aiCenterName | |||||
| resourceDetail.ComputeResource = resourceQueue.ComputeResource | resourceDetail.ComputeResource = resourceQueue.ComputeResource | ||||
| resourceDetail.AccCardType = resourceQueue.AccCardType + "(" + resourceQueue.ComputeResource + ")" | resourceDetail.AccCardType = resourceQueue.AccCardType + "(" + resourceQueue.ComputeResource + ")" | ||||
| resourceDetail.CardsTotalNum = resourceQueue.CardsTotalNum | resourceDetail.CardsTotalNum = resourceQueue.CardsTotalNum | ||||
| @@ -1554,7 +1623,7 @@ func getBeginAndEndTime(ctx *context.Context) (time.Time, time.Time) { | |||||
| ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) | ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) | ||||
| return beginTime, endTime | return beginTime, endTime | ||||
| } | } | ||||
| brainRecordBeginTime := recordCloudbrainDuration[0].CreatedUnix.AsTime() | |||||
| brainRecordBeginTime := recordCloudbrainDuration[0].DateTime.AsTime() | |||||
| beginTime = brainRecordBeginTime | beginTime = brainRecordBeginTime | ||||
| endTime = now | endTime = now | ||||
| } else if queryType == "today" { | } else if queryType == "today" { | ||||
| @@ -1596,7 +1665,7 @@ func getBeginAndEndTime(ctx *context.Context) (time.Time, time.Time) { | |||||
| ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) | ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) | ||||
| return beginTime, endTime | return beginTime, endTime | ||||
| } | } | ||||
| brainRecordBeginTime := recordCloudbrainDuration[0].CreatedUnix.AsTime() | |||||
| brainRecordBeginTime := recordCloudbrainDuration[0].DateTime.AsTime() | |||||
| beginTime = brainRecordBeginTime | beginTime = brainRecordBeginTime | ||||
| endTime = now | endTime = now | ||||
| } else { | } else { | ||||
| @@ -1627,7 +1696,7 @@ func getAiCenterUsageDuration(beginTime time.Time, endTime time.Time, cloudbrain | |||||
| usageRate := float64(0) | usageRate := float64(0) | ||||
| for _, cloudbrainStatistic := range cloudbrainStatistics { | for _, cloudbrainStatistic := range cloudbrainStatistics { | ||||
| if int64(cloudbrainStatistic.CreatedUnix) >= beginTime.Unix() && int64(cloudbrainStatistic.CreatedUnix) < endTime.Unix() { | |||||
| if int64(cloudbrainStatistic.DateTime) >= beginTime.Unix() && int64(cloudbrainStatistic.DateTime) < endTime.Unix() { | |||||
| totalDuration += cloudbrainStatistic.CardsTotalDuration | totalDuration += cloudbrainStatistic.CardsTotalDuration | ||||
| usageDuration += cloudbrainStatistic.CardsUseDuration | usageDuration += cloudbrainStatistic.CardsUseDuration | ||||
| } | } | ||||
| @@ -1659,28 +1728,29 @@ func getDurationStatistic(beginTime time.Time, endTime time.Time) (models.Durati | |||||
| return OpenIDurationRate, C2NetDurationRate, 0 | return OpenIDurationRate, C2NetDurationRate, 0 | ||||
| } | } | ||||
| for _, cloudbrainStatistic := range cardDurationStatistics { | for _, cloudbrainStatistic := range cardDurationStatistics { | ||||
| aiCenterName := cloudbrainStatistic.AiCenterCode + "/" + repo.GetAiCenterNameByCode(cloudbrainStatistic.AiCenterCode, "zh-CN") | |||||
| if cloudbrainStatistic.Cluster == models.OpenICluster { | if cloudbrainStatistic.Cluster == models.OpenICluster { | ||||
| if _, ok := OpenITotalDuration[cloudbrainStatistic.AiCenterName]; !ok { | |||||
| OpenITotalDuration[cloudbrainStatistic.AiCenterName] = cloudbrainStatistic.CardsTotalDuration | |||||
| if _, ok := OpenITotalDuration[aiCenterName]; !ok { | |||||
| OpenITotalDuration[aiCenterName] = cloudbrainStatistic.CardsTotalDuration | |||||
| } else { | } else { | ||||
| OpenITotalDuration[cloudbrainStatistic.AiCenterName] += cloudbrainStatistic.CardsTotalDuration | |||||
| OpenITotalDuration[aiCenterName] += cloudbrainStatistic.CardsTotalDuration | |||||
| } | } | ||||
| if _, ok := OpenIUsageDuration[cloudbrainStatistic.AiCenterName]; !ok { | |||||
| OpenIUsageDuration[cloudbrainStatistic.AiCenterName] = cloudbrainStatistic.CardsUseDuration | |||||
| if _, ok := OpenIUsageDuration[aiCenterName]; !ok { | |||||
| OpenIUsageDuration[aiCenterName] = cloudbrainStatistic.CardsUseDuration | |||||
| } else { | } else { | ||||
| OpenIUsageDuration[cloudbrainStatistic.AiCenterName] += cloudbrainStatistic.CardsUseDuration | |||||
| OpenIUsageDuration[aiCenterName] += cloudbrainStatistic.CardsUseDuration | |||||
| } | } | ||||
| } | } | ||||
| if cloudbrainStatistic.Cluster == models.C2NetCluster { | if cloudbrainStatistic.Cluster == models.C2NetCluster { | ||||
| if _, ok := C2NetTotalDuration[cloudbrainStatistic.AiCenterName]; !ok { | |||||
| C2NetTotalDuration[cloudbrainStatistic.AiCenterName] = cloudbrainStatistic.CardsTotalDuration | |||||
| if _, ok := C2NetTotalDuration[aiCenterName]; !ok { | |||||
| C2NetTotalDuration[aiCenterName] = cloudbrainStatistic.CardsTotalDuration | |||||
| } else { | } else { | ||||
| C2NetTotalDuration[cloudbrainStatistic.AiCenterName] += cloudbrainStatistic.CardsTotalDuration | |||||
| C2NetTotalDuration[aiCenterName] += cloudbrainStatistic.CardsTotalDuration | |||||
| } | } | ||||
| if _, ok := C2NetUsageDuration[cloudbrainStatistic.AiCenterName]; !ok { | |||||
| C2NetUsageDuration[cloudbrainStatistic.AiCenterName] = cloudbrainStatistic.CardsUseDuration | |||||
| if _, ok := C2NetUsageDuration[aiCenterName]; !ok { | |||||
| C2NetUsageDuration[aiCenterName] = cloudbrainStatistic.CardsUseDuration | |||||
| } else { | } else { | ||||
| C2NetUsageDuration[cloudbrainStatistic.AiCenterName] += cloudbrainStatistic.CardsUseDuration | |||||
| C2NetUsageDuration[aiCenterName] += cloudbrainStatistic.CardsUseDuration | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1690,16 +1760,17 @@ func getDurationStatistic(beginTime time.Time, endTime time.Time) (models.Durati | |||||
| return OpenIDurationRate, C2NetDurationRate, 0 | return OpenIDurationRate, C2NetDurationRate, 0 | ||||
| } | } | ||||
| for _, v := range ResourceAiCenterRes { | for _, v := range ResourceAiCenterRes { | ||||
| aiCenterName := v.AiCenterCode + "/" + repo.GetAiCenterNameByCode(v.AiCenterCode, "zh-CN") | |||||
| if cutString(v.AiCenterCode, 4) == cutString(models.AICenterOfCloudBrainOne, 4) { | if cutString(v.AiCenterCode, 4) == cutString(models.AICenterOfCloudBrainOne, 4) { | ||||
| if _, ok := OpenIUsageDuration[v.AiCenterName]; !ok { | |||||
| OpenIUsageDuration[v.AiCenterName] = 0 | |||||
| if _, ok := OpenIUsageDuration[aiCenterName]; !ok { | |||||
| OpenIUsageDuration[aiCenterName] = 0 | |||||
| } | } | ||||
| if _, ok := OpenITotalDuration[v.AiCenterName]; !ok { | |||||
| OpenITotalDuration[v.AiCenterName] = 0 | |||||
| if _, ok := OpenITotalDuration[aiCenterName]; !ok { | |||||
| OpenITotalDuration[aiCenterName] = 0 | |||||
| } | } | ||||
| } else { | } else { | ||||
| if _, ok := C2NetUsageDuration[v.AiCenterName]; !ok { | |||||
| C2NetUsageDuration[v.AiCenterName] = 0 | |||||
| if _, ok := C2NetUsageDuration[aiCenterName]; !ok { | |||||
| C2NetUsageDuration[aiCenterName] = 0 | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1716,7 +1787,7 @@ func getDurationStatistic(beginTime time.Time, endTime time.Time) (models.Durati | |||||
| for _, v := range OpenITotalDuration { | for _, v := range OpenITotalDuration { | ||||
| totalCanUse += float64(v) | totalCanUse += float64(v) | ||||
| } | } | ||||
| for _, v := range OpenIUsageRate { | |||||
| for _, v := range OpenIUsageDuration { | |||||
| totalUse += float64(v) | totalUse += float64(v) | ||||
| } | } | ||||
| if totalCanUse == 0 || totalUse == 0 { | if totalCanUse == 0 || totalUse == 0 { | ||||
| @@ -1724,6 +1795,7 @@ func getDurationStatistic(beginTime time.Time, endTime time.Time) (models.Durati | |||||
| } else { | } else { | ||||
| totalUsageRate = totalUse / totalCanUse | totalUsageRate = totalUse / totalCanUse | ||||
| } | } | ||||
| delete(C2NetUsageDuration, "/") | |||||
| OpenIDurationRate.AiCenterTotalDurationStat = OpenITotalDuration | OpenIDurationRate.AiCenterTotalDurationStat = OpenITotalDuration | ||||
| OpenIDurationRate.AiCenterUsageDurationStat = OpenIUsageDuration | OpenIDurationRate.AiCenterUsageDurationStat = OpenIUsageDuration | ||||
| @@ -1831,3 +1903,30 @@ func getHourCloudbrainDuration(beginTime time.Time, endTime time.Time, aiCenterC | |||||
| hourTimeStatistic.HourTimeUsageRate = hourTimeUsageRate | hourTimeStatistic.HourTimeUsageRate = hourTimeUsageRate | ||||
| return hourTimeStatistic, nil | return hourTimeStatistic, nil | ||||
| } | } | ||||
| func CloudbrainUpdateAiCenter(ctx *context.Context) { | |||||
| repo.CloudbrainDurationStatisticHour() | |||||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||||
| "message": 0, | |||||
| }) | |||||
| } | |||||
| func GetResourceQueues(ctx *context.Context) { | |||||
| resourceQueues, err := models.GetCanUseCardInfo() | |||||
| if err != nil { | |||||
| log.Info("GetCanUseCardInfo err: %v", err) | |||||
| return | |||||
| } | |||||
| Resource := make([]*models.ResourceQueue, 0) | |||||
| aiCenterCodeMap := make(map[string]string) | |||||
| for _, resourceQueue := range resourceQueues { | |||||
| if _, ok := aiCenterCodeMap[resourceQueue.AiCenterCode]; !ok { | |||||
| resourceQueue.AiCenterName = repo.GetAiCenterNameByCode(resourceQueue.AiCenterCode, ctx.Language()) | |||||
| aiCenterCodeMap[resourceQueue.AiCenterCode] = resourceQueue.AiCenterCode | |||||
| Resource = append(Resource, resourceQueue) | |||||
| } | |||||
| } | |||||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||||
| "resourceQueues": Resource, | |||||
| }) | |||||
| } | |||||
| @@ -150,7 +150,6 @@ func GetModelArtsTrainJobVersion(ctx *context.APIContext) { | |||||
| if len(result.JobInfo.Tasks) > 0 { | if len(result.JobInfo.Tasks) > 0 { | ||||
| if len(result.JobInfo.Tasks[0].CenterID) > 0 && len(result.JobInfo.Tasks[0].CenterName) > 0 { | if len(result.JobInfo.Tasks[0].CenterID) > 0 && len(result.JobInfo.Tasks[0].CenterName) > 0 { | ||||
| job.AiCenter = result.JobInfo.Tasks[0].CenterID[0] + "+" + result.JobInfo.Tasks[0].CenterName[0] | job.AiCenter = result.JobInfo.Tasks[0].CenterID[0] + "+" + result.JobInfo.Tasks[0].CenterName[0] | ||||
| // aiCenterName = result.JobInfo.Tasks[0].CenterName[0] | |||||
| aiCenterName = cloudbrainService.GetAiCenterShow(job.AiCenter, ctx.Context) | aiCenterName = cloudbrainService.GetAiCenterShow(job.AiCenter, ctx.Context) | ||||
| } | } | ||||
| } | } | ||||
| @@ -285,15 +284,6 @@ func TrainJobGetLog(ctx *context.APIContext) { | |||||
| return | return | ||||
| } | } | ||||
| prefix := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, modelarts.LogPath, versionName), "/") + "/job" | |||||
| _, err = storage.GetObsLogFileName(prefix) | |||||
| var canLogDownload bool | |||||
| if err != nil { | |||||
| canLogDownload = false | |||||
| } else { | |||||
| canLogDownload = true | |||||
| } | |||||
| ctx.Data["log_file_name"] = resultLogFile.LogFileList[0] | ctx.Data["log_file_name"] = resultLogFile.LogFileList[0] | ||||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | ctx.JSON(http.StatusOK, map[string]interface{}{ | ||||
| @@ -303,11 +293,23 @@ func TrainJobGetLog(ctx *context.APIContext) { | |||||
| "EndLine": result.EndLine, | "EndLine": result.EndLine, | ||||
| "Content": result.Content, | "Content": result.Content, | ||||
| "Lines": result.Lines, | "Lines": result.Lines, | ||||
| "CanLogDownload": canLogDownload, | |||||
| "CanLogDownload": canLogDownload(ctx.User, task), | |||||
| "StartTime": task.StartTime, | "StartTime": task.StartTime, | ||||
| }) | }) | ||||
| } | } | ||||
| func canLogDownload(user *models.User, task *models.Cloudbrain) bool { | |||||
| if task == nil || !task.IsUserHasRight(user) { | |||||
| return false | |||||
| } | |||||
| prefix := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, modelarts.LogPath, task.VersionName), "/") + "/job" | |||||
| _, err := storage.GetObsLogFileName(prefix) | |||||
| if err != nil { | |||||
| return false | |||||
| } | |||||
| return true | |||||
| } | |||||
| func trainJobGetLogContent(jobID string, versionID int64, baseLine string, order string, lines int) (*models.GetTrainJobLogFileNamesResult, *models.GetTrainJobLogResult, error) { | func trainJobGetLogContent(jobID string, versionID int64, baseLine string, order string, lines int) (*models.GetTrainJobLogFileNamesResult, *models.GetTrainJobLogResult, error) { | ||||
| resultLogFile, err := modelarts.GetTrainJobLogFileNames(jobID, strconv.FormatInt(versionID, 10)) | resultLogFile, err := modelarts.GetTrainJobLogFileNames(jobID, strconv.FormatInt(versionID, 10)) | ||||
| @@ -104,3 +104,12 @@ func ShowModelConvertPage(ctx *context.APIContext) { | |||||
| } | } | ||||
| } | } | ||||
| func QueryModelConvertById(ctx *context.APIContext) { | |||||
| modelResult, err := routerRepo.GetModelConvertById(ctx.Context) | |||||
| if err == nil { | |||||
| ctx.JSON(http.StatusOK, modelResult) | |||||
| } else { | |||||
| ctx.JSON(http.StatusOK, nil) | |||||
| } | |||||
| } | |||||
| @@ -6,9 +6,10 @@ | |||||
| package private | package private | ||||
| import ( | import ( | ||||
| "code.gitea.io/gitea/routers/admin" | |||||
| "strings" | "strings" | ||||
| "code.gitea.io/gitea/routers/admin" | |||||
| "code.gitea.io/gitea/routers/repo" | "code.gitea.io/gitea/routers/repo" | ||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| @@ -52,7 +53,9 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Get("/tool/org_stat", OrgStatisticManually) | m.Get("/tool/org_stat", OrgStatisticManually) | ||||
| m.Post("/tool/update_repo_visit/:date", UpdateRepoVisit) | m.Post("/tool/update_repo_visit/:date", UpdateRepoVisit) | ||||
| m.Post("/task/history_handle/duration", repo.HandleTaskWithNoDuration) | m.Post("/task/history_handle/duration", repo.HandleTaskWithNoDuration) | ||||
| m.Post("/task/history_handle/aicenter", repo.HandleTaskWithAiCenter) | |||||
| m.Post("/resources/specification/handle_historical_task", admin.RefreshHistorySpec) | m.Post("/resources/specification/handle_historical_task", admin.RefreshHistorySpec) | ||||
| m.Post("/duration_statisctic/history_handle", repo.CloudbrainUpdateHistoryData) | |||||
| }, CheckInternalToken) | }, CheckInternalToken) | ||||
| } | } | ||||
| @@ -150,6 +150,7 @@ func SaveModelConvert(ctx *context.Context) { | |||||
| go goCreateTask(modelConvert, ctx, task) | go goCreateTask(modelConvert, ctx, task) | ||||
| ctx.JSON(200, map[string]string{ | ctx.JSON(200, map[string]string{ | ||||
| "id": id, | |||||
| "code": "0", | "code": "0", | ||||
| }) | }) | ||||
| } | } | ||||
| @@ -726,6 +727,11 @@ func ShowModelConvertPageInfo(ctx *context.Context) { | |||||
| } | } | ||||
| } | } | ||||
| func GetModelConvertById(ctx *context.Context) (*models.AiModelConvert, error) { | |||||
| id := ctx.Query("id") | |||||
| return models.QueryModelConvertById(id) | |||||
| } | |||||
| func GetModelConvertPageData(ctx *context.Context) ([]*models.AiModelConvert, int64, error) { | func GetModelConvertPageData(ctx *context.Context) ([]*models.AiModelConvert, int64, error) { | ||||
| page := ctx.QueryInt("page") | page := ctx.QueryInt("page") | ||||
| if page <= 0 { | if page <= 0 { | ||||
| @@ -22,16 +22,24 @@ import ( | |||||
| ) | ) | ||||
| const ( | const ( | ||||
| Model_prefix = "aimodels/" | |||||
| tplModelManageIndex = "repo/modelmanage/index" | |||||
| tplModelManageDownload = "repo/modelmanage/download" | |||||
| tplModelInfo = "repo/modelmanage/showinfo" | |||||
| MODEL_LATEST = 1 | |||||
| MODEL_NOT_LATEST = 0 | |||||
| MODEL_MAX_SIZE = 1024 * 1024 * 1024 | |||||
| STATUS_COPY_MODEL = 1 | |||||
| STATUS_FINISHED = 0 | |||||
| STATUS_ERROR = 2 | |||||
| Attachment_model = "model" | |||||
| Model_prefix = "aimodels/" | |||||
| tplModelManageIndex = "repo/modelmanage/index" | |||||
| tplModelManageDownload = "repo/modelmanage/download" | |||||
| tplModelInfo = "repo/modelmanage/showinfo" | |||||
| tplCreateLocalModelInfo = "repo/modelmanage/create_local_1" | |||||
| tplCreateLocalForUploadModelInfo = "repo/modelmanage/create_local_2" | |||||
| tplCreateOnlineModelInfo = "repo/modelmanage/create_online" | |||||
| MODEL_LATEST = 1 | |||||
| MODEL_NOT_LATEST = 0 | |||||
| MODEL_MAX_SIZE = 1024 * 1024 * 1024 | |||||
| STATUS_COPY_MODEL = 1 | |||||
| STATUS_FINISHED = 0 | |||||
| STATUS_ERROR = 2 | |||||
| MODEL_LOCAL_TYPE = 1 | |||||
| MODEL_ONLINE_TYPE = 0 | |||||
| ) | ) | ||||
| func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, engine int, ctx *context.Context) (string, error) { | func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, engine int, ctx *context.Context) (string, error) { | ||||
| @@ -70,13 +78,12 @@ func saveModelByParameters(jobId string, versionName string, name string, versio | |||||
| cloudType = models.TypeCloudBrainTwo | cloudType = models.TypeCloudBrainTwo | ||||
| } else if aiTask.ComputeResource == models.GPUResource { | } else if aiTask.ComputeResource == models.GPUResource { | ||||
| cloudType = models.TypeCloudBrainOne | cloudType = models.TypeCloudBrainOne | ||||
| 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 | |||||
| } | |||||
| } | } | ||||
| spec, err := resource.GetCloudbrainSpec(aiTask.ID) | |||||
| if err == nil { | |||||
| specJson, _ := json.Marshal(spec) | |||||
| aiTask.FlavorName = string(specJson) | |||||
| } | |||||
| accuracy := make(map[string]string) | accuracy := make(map[string]string) | ||||
| accuracy["F1"] = "" | accuracy["F1"] = "" | ||||
| accuracy["Recall"] = "" | accuracy["Recall"] = "" | ||||
| @@ -189,6 +196,139 @@ func SaveNewNameModel(ctx *context.Context) { | |||||
| log.Info("save model end.") | log.Info("save model end.") | ||||
| } | } | ||||
| func SaveLocalModel(ctx *context.Context) { | |||||
| if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { | |||||
| ctx.Error(403, ctx.Tr("repo.model_noright")) | |||||
| return | |||||
| } | |||||
| re := map[string]string{ | |||||
| "code": "-1", | |||||
| } | |||||
| log.Info("save SaveLocalModel start.") | |||||
| uuid := uuid.NewV4() | |||||
| id := uuid.String() | |||||
| name := ctx.Query("name") | |||||
| version := ctx.Query("version") | |||||
| if version == "" { | |||||
| version = "0.0.1" | |||||
| } | |||||
| label := ctx.Query("label") | |||||
| description := ctx.Query("description") | |||||
| engine := ctx.QueryInt("engine") | |||||
| taskType := ctx.QueryInt("type") | |||||
| modelActualPath := "" | |||||
| if taskType == models.TypeCloudBrainOne { | |||||
| destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(id) + "/" | |||||
| modelActualPath = setting.Attachment.Minio.Bucket + "/" + destKeyNamePrefix | |||||
| } else if taskType == models.TypeCloudBrainTwo { | |||||
| destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(id) + "/" | |||||
| modelActualPath = setting.Bucket + "/" + destKeyNamePrefix | |||||
| } else { | |||||
| re["msg"] = "type is error." | |||||
| ctx.JSON(200, re) | |||||
| return | |||||
| } | |||||
| var lastNewModelId string | |||||
| repoId := ctx.Repo.Repository.ID | |||||
| aimodels := models.QueryModelByName(name, repoId) | |||||
| if len(aimodels) > 0 { | |||||
| for _, model := range aimodels { | |||||
| if model.Version == version { | |||||
| re["msg"] = ctx.Tr("repo.model.manage.create_error") | |||||
| ctx.JSON(200, re) | |||||
| return | |||||
| } | |||||
| if model.New == MODEL_LATEST { | |||||
| lastNewModelId = model.ID | |||||
| } | |||||
| } | |||||
| } | |||||
| model := &models.AiModelManage{ | |||||
| ID: id, | |||||
| Version: version, | |||||
| ModelType: MODEL_LOCAL_TYPE, | |||||
| VersionCount: len(aimodels) + 1, | |||||
| Label: label, | |||||
| Name: name, | |||||
| Description: description, | |||||
| New: MODEL_LATEST, | |||||
| Type: taskType, | |||||
| Path: modelActualPath, | |||||
| Size: 0, | |||||
| AttachmentId: "", | |||||
| RepoId: repoId, | |||||
| UserId: ctx.User.ID, | |||||
| Engine: int64(engine), | |||||
| TrainTaskInfo: "", | |||||
| Accuracy: "", | |||||
| Status: STATUS_FINISHED, | |||||
| } | |||||
| err := models.SaveModelToDb(model) | |||||
| if err != nil { | |||||
| re["msg"] = err.Error() | |||||
| ctx.JSON(200, re) | |||||
| return | |||||
| } | |||||
| if len(lastNewModelId) > 0 { | |||||
| //udpate status and version count | |||||
| models.ModifyModelNewProperty(lastNewModelId, MODEL_NOT_LATEST, 0) | |||||
| } | |||||
| var units []models.RepoUnit | |||||
| var deleteUnitTypes []models.UnitType | |||||
| units = append(units, models.RepoUnit{ | |||||
| RepoID: ctx.Repo.Repository.ID, | |||||
| Type: models.UnitTypeModelManage, | |||||
| Config: &models.ModelManageConfig{ | |||||
| EnableModelManage: true, | |||||
| }, | |||||
| }) | |||||
| deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeModelManage) | |||||
| models.UpdateRepositoryUnits(ctx.Repo.Repository, units, deleteUnitTypes) | |||||
| log.Info("save model end.") | |||||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, id, name, models.ActionCreateNewModelTask) | |||||
| re["code"] = "0" | |||||
| re["id"] = id | |||||
| ctx.JSON(200, re) | |||||
| } | |||||
| func getSize(files []storage.FileInfo) int64 { | |||||
| var size int64 | |||||
| for _, file := range files { | |||||
| size += file.Size | |||||
| } | |||||
| return size | |||||
| } | |||||
| func UpdateModelSize(modeluuid string) { | |||||
| model, err := models.QueryModelById(modeluuid) | |||||
| if err == nil { | |||||
| if model.Type == models.TypeCloudBrainOne { | |||||
| if strings.HasPrefix(model.Path, setting.Attachment.Minio.Bucket+"/"+Model_prefix) { | |||||
| files, err := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, model.Path[len(setting.Attachment.Minio.Bucket)+1:]) | |||||
| if err != nil { | |||||
| log.Info("Failed to query model size from minio. id=" + modeluuid) | |||||
| } | |||||
| size := getSize(files) | |||||
| models.ModifyModelSize(modeluuid, size) | |||||
| } | |||||
| } else if model.Type == models.TypeCloudBrainTwo { | |||||
| if strings.HasPrefix(model.Path, setting.Bucket+"/"+Model_prefix) { | |||||
| files, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, model.Path[len(setting.Bucket)+1:]) | |||||
| if err != nil { | |||||
| log.Info("Failed to query model size from obs. id=" + modeluuid) | |||||
| } | |||||
| size := getSize(files) | |||||
| models.ModifyModelSize(modeluuid, size) | |||||
| } | |||||
| } | |||||
| } else { | |||||
| log.Info("not found model,uuid=" + modeluuid) | |||||
| } | |||||
| } | |||||
| func SaveModel(ctx *context.Context) { | func SaveModel(ctx *context.Context) { | ||||
| if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { | if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { | ||||
| ctx.Error(403, ctx.Tr("repo.model_noright")) | ctx.Error(403, ctx.Tr("repo.model_noright")) | ||||
| @@ -292,6 +432,60 @@ func downloadModelFromCloudBrainOne(modelUUID string, jobName string, parentDir | |||||
| return "", 0, nil | return "", 0, nil | ||||
| } | } | ||||
| } | } | ||||
| func DeleteModelFile(ctx *context.Context) { | |||||
| log.Info("delete model start.") | |||||
| id := ctx.Query("id") | |||||
| fileName := ctx.Query("fileName") | |||||
| model, err := models.QueryModelById(id) | |||||
| if err == nil { | |||||
| if model.ModelType == MODEL_LOCAL_TYPE { | |||||
| if model.Type == models.TypeCloudBrainOne { | |||||
| bucketName := setting.Attachment.Minio.Bucket | |||||
| objectName := model.Path[len(bucketName)+1:] + fileName | |||||
| log.Info("delete bucket=" + bucketName + " path=" + objectName) | |||||
| if strings.HasPrefix(model.Path, bucketName+"/"+Model_prefix) { | |||||
| totalSize := storage.MinioGetFilesSize(bucketName, []string{objectName}) | |||||
| err := storage.Attachments.DeleteDir(objectName) | |||||
| if err != nil { | |||||
| log.Info("Failed to delete model. id=" + id) | |||||
| re := map[string]string{ | |||||
| "code": "-1", | |||||
| } | |||||
| re["msg"] = err.Error() | |||||
| ctx.JSON(200, re) | |||||
| return | |||||
| } else { | |||||
| log.Info("delete minio file size is:" + fmt.Sprint(totalSize)) | |||||
| models.ModifyModelSize(id, model.Size-totalSize) | |||||
| } | |||||
| } | |||||
| } else if model.Type == models.TypeCloudBrainTwo { | |||||
| bucketName := setting.Bucket | |||||
| objectName := model.Path[len(setting.Bucket)+1:] + fileName | |||||
| log.Info("delete bucket=" + setting.Bucket + " path=" + objectName) | |||||
| if strings.HasPrefix(model.Path, bucketName+"/"+Model_prefix) { | |||||
| totalSize := storage.ObsGetFilesSize(bucketName, []string{objectName}) | |||||
| err := storage.ObsRemoveObject(bucketName, objectName) | |||||
| if err != nil { | |||||
| log.Info("Failed to delete model. id=" + id) | |||||
| re := map[string]string{ | |||||
| "code": "-1", | |||||
| } | |||||
| re["msg"] = err.Error() | |||||
| ctx.JSON(200, re) | |||||
| return | |||||
| } else { | |||||
| log.Info("delete obs file size is:" + fmt.Sprint(totalSize)) | |||||
| models.ModifyModelSize(id, model.Size-totalSize) | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| ctx.JSON(200, map[string]string{ | |||||
| "code": "0", | |||||
| }) | |||||
| } | |||||
| func DeleteModel(ctx *context.Context) { | func DeleteModel(ctx *context.Context) { | ||||
| log.Info("delete model start.") | log.Info("delete model start.") | ||||
| @@ -317,14 +511,28 @@ func deleteModelByID(ctx *context.Context, id string) error { | |||||
| return errors.New(ctx.Tr("repo.model_noright")) | return errors.New(ctx.Tr("repo.model_noright")) | ||||
| } | } | ||||
| if err == nil { | if err == nil { | ||||
| log.Info("bucket=" + setting.Bucket + " path=" + model.Path) | |||||
| if strings.HasPrefix(model.Path, setting.Bucket+"/"+Model_prefix) { | |||||
| err := storage.ObsRemoveObject(setting.Bucket, model.Path[len(setting.Bucket)+1:]) | |||||
| if err != nil { | |||||
| log.Info("Failed to delete model. id=" + id) | |||||
| return err | |||||
| if model.Type == models.TypeCloudBrainOne { | |||||
| bucketName := setting.Attachment.Minio.Bucket | |||||
| log.Info("bucket=" + bucketName + " path=" + model.Path) | |||||
| if strings.HasPrefix(model.Path, bucketName+"/"+Model_prefix) { | |||||
| err := storage.Attachments.DeleteDir(model.Path[len(bucketName)+1:]) | |||||
| if err != nil { | |||||
| log.Info("Failed to delete model. id=" + id) | |||||
| return err | |||||
| } | |||||
| } | |||||
| } else if model.Type == models.TypeCloudBrainTwo { | |||||
| log.Info("bucket=" + setting.Bucket + " path=" + model.Path) | |||||
| if strings.HasPrefix(model.Path, setting.Bucket+"/"+Model_prefix) { | |||||
| err := storage.ObsRemoveObject(setting.Bucket, model.Path[len(setting.Bucket)+1:]) | |||||
| if err != nil { | |||||
| log.Info("Failed to delete model. id=" + id) | |||||
| return err | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| err = models.DeleteModelById(id) | err = models.DeleteModelById(id) | ||||
| if err == nil { //find a model to change new | if err == nil { //find a model to change new | ||||
| aimodels := models.QueryModelByName(model.Name, model.RepoId) | aimodels := models.QueryModelByName(model.Name, model.RepoId) | ||||
| @@ -884,29 +1092,58 @@ func ModifyModel(id string, description string) error { | |||||
| func ModifyModelInfo(ctx *context.Context) { | func ModifyModelInfo(ctx *context.Context) { | ||||
| log.Info("modify model start.") | log.Info("modify model start.") | ||||
| id := ctx.Query("id") | id := ctx.Query("id") | ||||
| description := ctx.Query("description") | |||||
| re := map[string]string{ | |||||
| "code": "-1", | |||||
| } | |||||
| task, err := models.QueryModelById(id) | task, err := models.QueryModelById(id) | ||||
| if err != nil { | if err != nil { | ||||
| re["msg"] = err.Error() | |||||
| log.Error("no such model!", err.Error()) | log.Error("no such model!", err.Error()) | ||||
| ctx.ServerError("no such model:", err) | |||||
| ctx.JSON(200, re) | |||||
| return | return | ||||
| } | } | ||||
| if !isOper(ctx, task.UserId) { | if !isOper(ctx, task.UserId) { | ||||
| ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||||
| //ctx.ServerError("no right.", errors.New(ctx.Tr("repo.model_noright"))) | |||||
| re["msg"] = "No right to operation." | |||||
| ctx.JSON(200, re) | |||||
| return | return | ||||
| } | } | ||||
| if task.ModelType == MODEL_LOCAL_TYPE { | |||||
| name := ctx.Query("name") | |||||
| label := ctx.Query("label") | |||||
| description := ctx.Query("description") | |||||
| engine := ctx.QueryInt("engine") | |||||
| aimodels := models.QueryModelByName(name, task.RepoId) | |||||
| if aimodels != nil && len(aimodels) > 0 { | |||||
| if len(aimodels) == 1 { | |||||
| if aimodels[0].ID != task.ID { | |||||
| re["msg"] = ctx.Tr("repo.model.manage.create_error") | |||||
| ctx.JSON(200, re) | |||||
| return | |||||
| } | |||||
| } else { | |||||
| re["msg"] = ctx.Tr("repo.model.manage.create_error") | |||||
| ctx.JSON(200, re) | |||||
| return | |||||
| } | |||||
| } | |||||
| err = models.ModifyLocalModel(id, name, label, description, engine) | |||||
| err = ModifyModel(id, description) | |||||
| } else { | |||||
| label := ctx.Query("label") | |||||
| description := ctx.Query("description") | |||||
| engine := task.Engine | |||||
| name := task.Name | |||||
| err = models.ModifyLocalModel(id, name, label, description, int(engine)) | |||||
| } | |||||
| if err != nil { | if err != nil { | ||||
| log.Info("modify error," + err.Error()) | |||||
| ctx.ServerError("error.", err) | |||||
| re["msg"] = err.Error() | |||||
| ctx.JSON(200, re) | |||||
| return | |||||
| } else { | } else { | ||||
| ctx.JSON(200, "success") | |||||
| re["code"] = "0" | |||||
| ctx.JSON(200, re) | |||||
| } | } | ||||
| } | } | ||||
| func QueryModelListForPredict(ctx *context.Context) { | func QueryModelListForPredict(ctx *context.Context) { | ||||
| @@ -1004,3 +1241,25 @@ func QueryOneLevelModelFile(ctx *context.Context) { | |||||
| ctx.JSON(http.StatusOK, fileinfos) | ctx.JSON(http.StatusOK, fileinfos) | ||||
| } | } | ||||
| } | } | ||||
| func CreateLocalModel(ctx *context.Context) { | |||||
| ctx.Data["isModelManage"] = true | |||||
| ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage) | |||||
| ctx.HTML(200, tplCreateLocalModelInfo) | |||||
| } | |||||
| func CreateLocalModelForUpload(ctx *context.Context) { | |||||
| ctx.Data["uuid"] = ctx.Query("uuid") | |||||
| ctx.Data["isModelManage"] = true | |||||
| ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage) | |||||
| ctx.Data["max_model_size"] = setting.MaxModelSize * MODEL_MAX_SIZE | |||||
| ctx.HTML(200, tplCreateLocalForUploadModelInfo) | |||||
| } | |||||
| func CreateOnlineModel(ctx *context.Context) { | |||||
| ctx.Data["isModelManage"] = true | |||||
| ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage) | |||||
| ctx.HTML(200, tplCreateOnlineModelInfo) | |||||
| } | |||||
| @@ -11,6 +11,7 @@ import ( | |||||
| "fmt" | "fmt" | ||||
| "mime/multipart" | "mime/multipart" | ||||
| "net/http" | "net/http" | ||||
| "path" | |||||
| "strconv" | "strconv" | ||||
| "strings" | "strings" | ||||
| @@ -311,7 +312,8 @@ func GetAttachment(ctx *context.Context) { | |||||
| url = setting.PROXYURL + "/obs_proxy_download?uuid=" + attach.UUID + "&file_name=" + attach.Name | url = setting.PROXYURL + "/obs_proxy_download?uuid=" + attach.UUID + "&file_name=" + attach.Name | ||||
| log.Info("return url=" + url) | log.Info("return url=" + url) | ||||
| } else { | } else { | ||||
| url, err = storage.ObsGetPreSignedUrl(attach.UUID, attach.Name) | |||||
| objectName := strings.TrimPrefix(path.Join(setting.BasePath, path.Join(attach.UUID[0:1], attach.UUID[1:2], attach.UUID, attach.Name)), "/") | |||||
| url, err = storage.ObsGetPreSignedUrl(objectName, attach.Name) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.ServerError("ObsGetPreSignedUrl", err) | ctx.ServerError("ObsGetPreSignedUrl", err) | ||||
| return | return | ||||
| @@ -415,7 +417,7 @@ func AddAttachment(ctx *context.Context) { | |||||
| uuid := ctx.Query("uuid") | uuid := ctx.Query("uuid") | ||||
| has := false | has := false | ||||
| if typeCloudBrain == models.TypeCloudBrainOne { | if typeCloudBrain == models.TypeCloudBrainOne { | ||||
| has, err = storage.Attachments.HasObject(models.AttachmentRelativePath(uuid)) | |||||
| has, err = storage.Attachments.HasObject(setting.Attachment.Minio.BasePath + models.AttachmentRelativePath(uuid)) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.ServerError("HasObject", err) | ctx.ServerError("HasObject", err) | ||||
| return | return | ||||
| @@ -557,7 +559,7 @@ func GetSuccessChunks(ctx *context.Context) { | |||||
| isExist := false | isExist := false | ||||
| if typeCloudBrain == models.TypeCloudBrainOne { | if typeCloudBrain == models.TypeCloudBrainOne { | ||||
| isExist, err = storage.Attachments.HasObject(models.AttachmentRelativePath(fileChunk.UUID)) | |||||
| isExist, err = storage.Attachments.HasObject(setting.Attachment.Minio.BasePath + models.AttachmentRelativePath(fileChunk.UUID)) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.ServerError("HasObject failed", err) | ctx.ServerError("HasObject failed", err) | ||||
| return | return | ||||
| @@ -593,12 +595,12 @@ func GetSuccessChunks(ctx *context.Context) { | |||||
| } | } | ||||
| if typeCloudBrain == models.TypeCloudBrainOne { | if typeCloudBrain == models.TypeCloudBrainOne { | ||||
| chunks, err = storage.GetPartInfos(fileChunk.UUID, fileChunk.UploadID) | |||||
| chunks, err = storage.GetPartInfos(strings.TrimPrefix(path.Join(setting.Attachment.Minio.BasePath, path.Join(fileChunk.UUID[0:1], fileChunk.UUID[1:2], fileChunk.UUID)), "/"), fileChunk.UploadID) | |||||
| if err != nil { | if err != nil { | ||||
| log.Error("GetPartInfos failed:%v", err.Error()) | log.Error("GetPartInfos failed:%v", err.Error()) | ||||
| } | } | ||||
| } else { | } else { | ||||
| chunks, err = storage.GetObsPartInfos(fileChunk.UUID, fileChunk.UploadID, fileName) | |||||
| chunks, err = storage.GetObsPartInfos(strings.TrimPrefix(path.Join(setting.BasePath, path.Join(fileChunk.UUID[0:1], fileChunk.UUID[1:2], fileChunk.UUID, fileName)), "/"), fileChunk.UploadID) | |||||
| if err != nil { | if err != nil { | ||||
| log.Error("GetObsPartInfos failed:%v", err.Error()) | log.Error("GetObsPartInfos failed:%v", err.Error()) | ||||
| } | } | ||||
| @@ -699,13 +701,13 @@ func NewMultipart(ctx *context.Context) { | |||||
| uuid := gouuid.NewV4().String() | uuid := gouuid.NewV4().String() | ||||
| var uploadID string | var uploadID string | ||||
| if typeCloudBrain == models.TypeCloudBrainOne { | if typeCloudBrain == models.TypeCloudBrainOne { | ||||
| uploadID, err = storage.NewMultiPartUpload(uuid) | |||||
| uploadID, err = storage.NewMultiPartUpload(strings.TrimPrefix(path.Join(setting.Attachment.Minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/")) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.ServerError("NewMultipart", err) | ctx.ServerError("NewMultipart", err) | ||||
| return | return | ||||
| } | } | ||||
| } else { | } else { | ||||
| uploadID, err = storage.NewObsMultiPartUpload(uuid, fileName) | |||||
| uploadID, err = storage.NewObsMultiPartUpload(strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/")) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.ServerError("NewObsMultiPartUpload", err) | ctx.ServerError("NewObsMultiPartUpload", err) | ||||
| return | return | ||||
| @@ -749,8 +751,8 @@ func PutOBSProxyUpload(ctx *context.Context) { | |||||
| ctx.Error(500, fmt.Sprintf("FormFile: %v", RequestBody)) | ctx.Error(500, fmt.Sprintf("FormFile: %v", RequestBody)) | ||||
| return | return | ||||
| } | } | ||||
| err := storage.ObsMultiPartUpload(uuid, uploadID, partNumber, fileName, RequestBody.ReadCloser()) | |||||
| objectName := strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| err := storage.ObsMultiPartUpload(objectName, uploadID, partNumber, fileName, RequestBody.ReadCloser()) | |||||
| if err != nil { | if err != nil { | ||||
| log.Info("upload error.") | log.Info("upload error.") | ||||
| } | } | ||||
| @@ -759,8 +761,8 @@ func PutOBSProxyUpload(ctx *context.Context) { | |||||
| func GetOBSProxyDownload(ctx *context.Context) { | func GetOBSProxyDownload(ctx *context.Context) { | ||||
| uuid := ctx.Query("uuid") | uuid := ctx.Query("uuid") | ||||
| fileName := ctx.Query("file_name") | fileName := ctx.Query("file_name") | ||||
| body, err := storage.ObsDownload(uuid, fileName) | |||||
| objectName := strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") | |||||
| body, err := storage.ObsDownloadAFile(setting.Bucket, objectName) | |||||
| if err != nil { | if err != nil { | ||||
| log.Info("upload error.") | log.Info("upload error.") | ||||
| } else { | } else { | ||||
| @@ -805,7 +807,7 @@ func GetMultipartUploadUrl(ctx *context.Context) { | |||||
| return | return | ||||
| } | } | ||||
| url, err = storage.GenMultiPartSignedUrl(uuid, uploadID, partNumber, size) | |||||
| url, err = storage.GenMultiPartSignedUrl(strings.TrimPrefix(path.Join(setting.Attachment.Minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/"), uploadID, partNumber, size) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.Error(500, fmt.Sprintf("GenMultiPartSignedUrl failed: %v", err)) | ctx.Error(500, fmt.Sprintf("GenMultiPartSignedUrl failed: %v", err)) | ||||
| return | return | ||||
| @@ -815,7 +817,7 @@ func GetMultipartUploadUrl(ctx *context.Context) { | |||||
| url = setting.PROXYURL + "/obs_proxy_multipart?uuid=" + uuid + "&uploadId=" + uploadID + "&partNumber=" + fmt.Sprint(partNumber) + "&file_name=" + fileName | url = setting.PROXYURL + "/obs_proxy_multipart?uuid=" + uuid + "&uploadId=" + uploadID + "&partNumber=" + fmt.Sprint(partNumber) + "&file_name=" + fileName | ||||
| log.Info("return url=" + url) | log.Info("return url=" + url) | ||||
| } else { | } else { | ||||
| url, err = storage.ObsGenMultiPartSignedUrl(uuid, uploadID, partNumber, fileName) | |||||
| url, err = storage.ObsGenMultiPartSignedUrl(strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/"), uploadID, partNumber) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.Error(500, fmt.Sprintf("ObsGenMultiPartSignedUrl failed: %v", err)) | ctx.Error(500, fmt.Sprintf("ObsGenMultiPartSignedUrl failed: %v", err)) | ||||
| return | return | ||||
| @@ -823,7 +825,6 @@ func GetMultipartUploadUrl(ctx *context.Context) { | |||||
| log.Info("url=" + url) | log.Info("url=" + url) | ||||
| } | } | ||||
| } | } | ||||
| ctx.JSON(200, map[string]string{ | ctx.JSON(200, map[string]string{ | ||||
| "url": url, | "url": url, | ||||
| }) | }) | ||||
| @@ -855,13 +856,13 @@ func CompleteMultipart(ctx *context.Context) { | |||||
| } | } | ||||
| if typeCloudBrain == models.TypeCloudBrainOne { | if typeCloudBrain == models.TypeCloudBrainOne { | ||||
| _, err = storage.CompleteMultiPartUpload(uuid, uploadID, fileChunk.TotalChunks) | |||||
| _, err = storage.CompleteMultiPartUpload(strings.TrimPrefix(path.Join(setting.Attachment.Minio.BasePath, path.Join(fileChunk.UUID[0:1], fileChunk.UUID[1:2], fileChunk.UUID)), "/"), uploadID, fileChunk.TotalChunks) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.Error(500, fmt.Sprintf("CompleteMultiPartUpload failed: %v", err)) | ctx.Error(500, fmt.Sprintf("CompleteMultiPartUpload failed: %v", err)) | ||||
| return | return | ||||
| } | } | ||||
| } else { | } else { | ||||
| err = storage.CompleteObsMultiPartUpload(uuid, uploadID, fileName, fileChunk.TotalChunks) | |||||
| err = storage.CompleteObsMultiPartUpload(strings.TrimPrefix(path.Join(setting.BasePath, path.Join(fileChunk.UUID[0:1], fileChunk.UUID[1:2], fileChunk.UUID, fileName)), "/"), uploadID, fileChunk.TotalChunks) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.Error(500, fmt.Sprintf("CompleteObsMultiPartUpload failed: %v", err)) | ctx.Error(500, fmt.Sprintf("CompleteObsMultiPartUpload failed: %v", err)) | ||||
| return | return | ||||
| @@ -1013,7 +1014,7 @@ func queryDatasets(ctx *context.Context, attachs []*models.AttachmentUsername) { | |||||
| } | } | ||||
| for _, attch := range attachs { | for _, attch := range attachs { | ||||
| has, err := storage.Attachments.HasObject(models.AttachmentRelativePath(attch.UUID)) | |||||
| has, err := storage.Attachments.HasObject(setting.Attachment.Minio.BasePath + models.AttachmentRelativePath(attch.UUID)) | |||||
| if err != nil || !has { | if err != nil || !has { | ||||
| continue | continue | ||||
| } | } | ||||
| @@ -0,0 +1,323 @@ | |||||
| package repo | |||||
| import ( | |||||
| "fmt" | |||||
| "path" | |||||
| "strconv" | |||||
| "strings" | |||||
| "code.gitea.io/gitea/models" | |||||
| "code.gitea.io/gitea/modules/context" | |||||
| "code.gitea.io/gitea/modules/log" | |||||
| "code.gitea.io/gitea/modules/minio_ext" | |||||
| "code.gitea.io/gitea/modules/setting" | |||||
| "code.gitea.io/gitea/modules/storage" | |||||
| "code.gitea.io/gitea/modules/upload" | |||||
| gouuid "github.com/satori/go.uuid" | |||||
| ) | |||||
| func GetModelChunks(ctx *context.Context) { | |||||
| fileMD5 := ctx.Query("md5") | |||||
| typeCloudBrain := ctx.QueryInt("type") | |||||
| fileName := ctx.Query("file_name") | |||||
| scene := ctx.Query("scene") | |||||
| modeluuid := ctx.Query("modeluuid") | |||||
| log.Info("scene=" + scene + " typeCloudBrain=" + fmt.Sprint(typeCloudBrain)) | |||||
| var chunks string | |||||
| err := checkTypeCloudBrain(typeCloudBrain) | |||||
| if err != nil { | |||||
| ctx.ServerError("checkTypeCloudBrain failed", err) | |||||
| return | |||||
| } | |||||
| fileChunk, err := models.GetModelFileChunkByMD5AndUser(fileMD5, ctx.User.ID, typeCloudBrain, modeluuid) | |||||
| if err != nil { | |||||
| if models.IsErrFileChunkNotExist(err) { | |||||
| ctx.JSON(200, map[string]string{ | |||||
| "uuid": "", | |||||
| "uploaded": "0", | |||||
| "uploadID": "", | |||||
| "chunks": "", | |||||
| }) | |||||
| } else { | |||||
| ctx.ServerError("GetFileChunkByMD5", err) | |||||
| } | |||||
| return | |||||
| } | |||||
| isExist := false | |||||
| if typeCloudBrain == models.TypeCloudBrainOne { | |||||
| isExist, err = storage.Attachments.HasObject(fileChunk.ObjectName) | |||||
| if isExist { | |||||
| log.Info("The file is exist in minio. has uploaded.path=" + fileChunk.ObjectName) | |||||
| } else { | |||||
| log.Info("The file is not exist in minio..") | |||||
| } | |||||
| if err != nil { | |||||
| ctx.ServerError("HasObject failed", err) | |||||
| return | |||||
| } | |||||
| } else { | |||||
| isExist, err = storage.ObsHasObject(fileChunk.ObjectName) | |||||
| if isExist { | |||||
| log.Info("The file is exist in obs. has uploaded. path=" + fileChunk.ObjectName) | |||||
| } else { | |||||
| log.Info("The file is not exist in obs.") | |||||
| } | |||||
| if err != nil { | |||||
| ctx.ServerError("ObsHasObject failed", err) | |||||
| return | |||||
| } | |||||
| } | |||||
| if isExist { | |||||
| if fileChunk.IsUploaded == models.FileNotUploaded { | |||||
| log.Info("the file has been uploaded but not recorded") | |||||
| fileChunk.IsUploaded = models.FileUploaded | |||||
| if err = models.UpdateModelFileChunk(fileChunk); err != nil { | |||||
| log.Error("UpdateFileChunk failed:", err.Error()) | |||||
| } | |||||
| } | |||||
| modelname := "" | |||||
| model, err := models.QueryModelById(modeluuid) | |||||
| if err == nil && model != nil { | |||||
| modelname = model.Name | |||||
| } | |||||
| ctx.JSON(200, map[string]string{ | |||||
| "uuid": fileChunk.UUID, | |||||
| "uploaded": strconv.Itoa(fileChunk.IsUploaded), | |||||
| "uploadID": fileChunk.UploadID, | |||||
| "chunks": string(chunks), | |||||
| "attachID": "0", | |||||
| "modeluuid": modeluuid, | |||||
| "fileName": fileName, | |||||
| "modelName": modelname, | |||||
| }) | |||||
| } else { | |||||
| if fileChunk.IsUploaded == models.FileUploaded { | |||||
| log.Info("the file has been recorded but not uploaded") | |||||
| fileChunk.IsUploaded = models.FileNotUploaded | |||||
| if err = models.UpdateModelFileChunk(fileChunk); err != nil { | |||||
| log.Error("UpdateFileChunk failed:", err.Error()) | |||||
| } | |||||
| } | |||||
| if typeCloudBrain == models.TypeCloudBrainOne { | |||||
| chunks, err = storage.GetPartInfos(fileChunk.ObjectName, fileChunk.UploadID) | |||||
| if err != nil { | |||||
| log.Error("GetPartInfos failed:%v", err.Error()) | |||||
| } | |||||
| } else { | |||||
| chunks, err = storage.GetObsPartInfos(fileChunk.ObjectName, fileChunk.UploadID) | |||||
| if err != nil { | |||||
| log.Error("GetObsPartInfos failed:%v", err.Error()) | |||||
| } | |||||
| } | |||||
| if err != nil { | |||||
| models.DeleteModelFileChunk(fileChunk) | |||||
| ctx.JSON(200, map[string]string{ | |||||
| "uuid": "", | |||||
| "uploaded": "0", | |||||
| "uploadID": "", | |||||
| "chunks": "", | |||||
| }) | |||||
| } else { | |||||
| ctx.JSON(200, map[string]string{ | |||||
| "uuid": fileChunk.UUID, | |||||
| "uploaded": strconv.Itoa(fileChunk.IsUploaded), | |||||
| "uploadID": fileChunk.UploadID, | |||||
| "chunks": string(chunks), | |||||
| "attachID": "0", | |||||
| "datasetID": "0", | |||||
| "fileName": "", | |||||
| "datasetName": "", | |||||
| }) | |||||
| } | |||||
| } | |||||
| } | |||||
| func getObjectName(filename string, modeluuid string) string { | |||||
| return strings.TrimPrefix(path.Join(Model_prefix, path.Join(modeluuid[0:1], modeluuid[1:2], modeluuid, filename)), "/") | |||||
| } | |||||
| func NewModelMultipart(ctx *context.Context) { | |||||
| if !setting.Attachment.Enabled { | |||||
| ctx.Error(404, "attachment is not enabled") | |||||
| return | |||||
| } | |||||
| fileName := ctx.Query("file_name") | |||||
| modeluuid := ctx.Query("modeluuid") | |||||
| err := upload.VerifyFileType(ctx.Query("fileType"), strings.Split(setting.Attachment.AllowedTypes, ",")) | |||||
| if err != nil { | |||||
| ctx.Error(400, err.Error()) | |||||
| return | |||||
| } | |||||
| typeCloudBrain := ctx.QueryInt("type") | |||||
| err = checkTypeCloudBrain(typeCloudBrain) | |||||
| if err != nil { | |||||
| ctx.ServerError("checkTypeCloudBrain failed", err) | |||||
| return | |||||
| } | |||||
| if setting.Attachment.StoreType == storage.MinioStorageType { | |||||
| totalChunkCounts := ctx.QueryInt("totalChunkCounts") | |||||
| if totalChunkCounts > minio_ext.MaxPartsCount { | |||||
| ctx.Error(400, fmt.Sprintf("chunk counts(%d) is too much", totalChunkCounts)) | |||||
| return | |||||
| } | |||||
| fileSize := ctx.QueryInt64("size") | |||||
| if fileSize > minio_ext.MaxMultipartPutObjectSize { | |||||
| ctx.Error(400, fmt.Sprintf("file size(%d) is too big", fileSize)) | |||||
| return | |||||
| } | |||||
| uuid := gouuid.NewV4().String() | |||||
| var uploadID string | |||||
| var objectName string | |||||
| if typeCloudBrain == models.TypeCloudBrainOne { | |||||
| objectName = strings.TrimPrefix(path.Join(Model_prefix, path.Join(modeluuid[0:1], modeluuid[1:2], modeluuid, fileName)), "/") | |||||
| uploadID, err = storage.NewMultiPartUpload(objectName) | |||||
| if err != nil { | |||||
| ctx.ServerError("NewMultipart", err) | |||||
| return | |||||
| } | |||||
| } else { | |||||
| objectName = strings.TrimPrefix(path.Join(Model_prefix, path.Join(modeluuid[0:1], modeluuid[1:2], modeluuid, fileName)), "/") | |||||
| uploadID, err = storage.NewObsMultiPartUpload(objectName) | |||||
| if err != nil { | |||||
| ctx.ServerError("NewObsMultiPartUpload", err) | |||||
| return | |||||
| } | |||||
| } | |||||
| _, err = models.InsertModelFileChunk(&models.ModelFileChunk{ | |||||
| UUID: uuid, | |||||
| UserID: ctx.User.ID, | |||||
| UploadID: uploadID, | |||||
| Md5: ctx.Query("md5"), | |||||
| Size: fileSize, | |||||
| ObjectName: objectName, | |||||
| ModelUUID: modeluuid, | |||||
| TotalChunks: totalChunkCounts, | |||||
| Type: typeCloudBrain, | |||||
| }) | |||||
| if err != nil { | |||||
| ctx.Error(500, fmt.Sprintf("InsertFileChunk: %v", err)) | |||||
| return | |||||
| } | |||||
| ctx.JSON(200, map[string]string{ | |||||
| "uuid": uuid, | |||||
| "uploadID": uploadID, | |||||
| }) | |||||
| } else { | |||||
| ctx.Error(404, "storage type is not enabled") | |||||
| return | |||||
| } | |||||
| } | |||||
| func GetModelMultipartUploadUrl(ctx *context.Context) { | |||||
| uuid := ctx.Query("uuid") | |||||
| uploadID := ctx.Query("uploadID") | |||||
| partNumber := ctx.QueryInt("chunkNumber") | |||||
| size := ctx.QueryInt64("size") | |||||
| typeCloudBrain := ctx.QueryInt("type") | |||||
| err := checkTypeCloudBrain(typeCloudBrain) | |||||
| if err != nil { | |||||
| ctx.ServerError("checkTypeCloudBrain failed", err) | |||||
| return | |||||
| } | |||||
| fileChunk, err := models.GetModelFileChunkByUUID(uuid) | |||||
| if err != nil { | |||||
| if models.IsErrFileChunkNotExist(err) { | |||||
| ctx.Error(404) | |||||
| } else { | |||||
| ctx.ServerError("GetFileChunkByUUID", err) | |||||
| } | |||||
| return | |||||
| } | |||||
| url := "" | |||||
| if typeCloudBrain == models.TypeCloudBrainOne { | |||||
| if size > minio_ext.MinPartSize { | |||||
| ctx.Error(400, fmt.Sprintf("chunk size(%d) is too big", size)) | |||||
| return | |||||
| } | |||||
| url, err = storage.GenMultiPartSignedUrl(fileChunk.ObjectName, uploadID, partNumber, size) | |||||
| if err != nil { | |||||
| ctx.Error(500, fmt.Sprintf("GenMultiPartSignedUrl failed: %v", err)) | |||||
| return | |||||
| } | |||||
| } else { | |||||
| url, err = storage.ObsGenMultiPartSignedUrl(fileChunk.ObjectName, uploadID, partNumber) | |||||
| if err != nil { | |||||
| ctx.Error(500, fmt.Sprintf("ObsGenMultiPartSignedUrl failed: %v", err)) | |||||
| return | |||||
| } | |||||
| log.Info("url=" + url) | |||||
| } | |||||
| ctx.JSON(200, map[string]string{ | |||||
| "url": url, | |||||
| }) | |||||
| } | |||||
| func CompleteModelMultipart(ctx *context.Context) { | |||||
| uuid := ctx.Query("uuid") | |||||
| uploadID := ctx.Query("uploadID") | |||||
| typeCloudBrain := ctx.QueryInt("type") | |||||
| modeluuid := ctx.Query("modeluuid") | |||||
| log.Warn("uuid:" + uuid) | |||||
| log.Warn("modeluuid:" + modeluuid) | |||||
| log.Warn("typeCloudBrain:" + strconv.Itoa(typeCloudBrain)) | |||||
| err := checkTypeCloudBrain(typeCloudBrain) | |||||
| if err != nil { | |||||
| ctx.ServerError("checkTypeCloudBrain failed", err) | |||||
| return | |||||
| } | |||||
| fileChunk, err := models.GetModelFileChunkByUUID(uuid) | |||||
| if err != nil { | |||||
| if models.IsErrFileChunkNotExist(err) { | |||||
| ctx.Error(404) | |||||
| } else { | |||||
| ctx.ServerError("GetFileChunkByUUID", err) | |||||
| } | |||||
| return | |||||
| } | |||||
| if typeCloudBrain == models.TypeCloudBrainOne { | |||||
| _, err = storage.CompleteMultiPartUpload(fileChunk.ObjectName, uploadID, fileChunk.TotalChunks) | |||||
| if err != nil { | |||||
| ctx.Error(500, fmt.Sprintf("CompleteMultiPartUpload failed: %v", err)) | |||||
| return | |||||
| } | |||||
| } else { | |||||
| err = storage.CompleteObsMultiPartUpload(fileChunk.ObjectName, uploadID, fileChunk.TotalChunks) | |||||
| if err != nil { | |||||
| ctx.Error(500, fmt.Sprintf("CompleteObsMultiPartUpload failed: %v", err)) | |||||
| return | |||||
| } | |||||
| } | |||||
| fileChunk.IsUploaded = models.FileUploaded | |||||
| err = models.UpdateModelFileChunk(fileChunk) | |||||
| if err != nil { | |||||
| ctx.Error(500, fmt.Sprintf("UpdateFileChunk: %v", err)) | |||||
| return | |||||
| } | |||||
| //更新模型大小信息 | |||||
| UpdateModelSize(modeluuid) | |||||
| ctx.JSON(200, map[string]string{ | |||||
| "result_code": "0", | |||||
| }) | |||||
| } | |||||
| @@ -1,38 +1,87 @@ | |||||
| package repo | package repo | ||||
| import ( | import ( | ||||
| "net/http" | |||||
| "strings" | "strings" | ||||
| "time" | "time" | ||||
| "code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
| "code.gitea.io/gitea/modules/context" | |||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| "code.gitea.io/gitea/modules/timeutil" | "code.gitea.io/gitea/modules/timeutil" | ||||
| cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||||
| ) | ) | ||||
| func CloudbrainDurationStatisticHour() { | func CloudbrainDurationStatisticHour() { | ||||
| dateTime := time.Now().Format("2006-01-02 15:04:05") | |||||
| dayTime := time.Now().Format("2006-01-02") | |||||
| var statisticTime time.Time | |||||
| var count int64 | |||||
| recordDurationUpdateTime, err := models.GetDurationRecordUpdateTime() | |||||
| if err != nil { | |||||
| log.Error("Can not get GetDurationRecordBeginTime", err) | |||||
| } | |||||
| now := time.Now() | now := time.Now() | ||||
| currentTime := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location()) | currentTime := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location()) | ||||
| if err == nil && len(recordDurationUpdateTime) > 0 { | |||||
| statisticTime = time.Unix(int64(recordDurationUpdateTime[0].DateTime), 0).Add(+1 * time.Hour) | |||||
| } else { | |||||
| statisticTime = currentTime | |||||
| } | |||||
| deleteBeginTime := time.Unix(int64(recordDurationUpdateTime[0].DateTime), 0) | |||||
| err = models.DeleteCloudbrainDurationStatistic(timeutil.TimeStamp(deleteBeginTime.Unix()), timeutil.TimeStamp(currentTime.Unix())) | |||||
| if err != nil { | |||||
| log.Error("DeleteCloudbrainDurationStatistic failed", err) | |||||
| } | |||||
| for statisticTime.Before(currentTime) || statisticTime.Equal(currentTime) { | |||||
| countEach := summaryDurationStat(statisticTime) | |||||
| count += countEach | |||||
| statisticTime = statisticTime.Add(+1 * time.Hour) | |||||
| } | |||||
| log.Info("summaryDurationStat count: %v", count) | |||||
| } | |||||
| func UpdateDurationStatisticHistoryData(beginTime time.Time, endTime time.Time) int64 { | |||||
| var count int64 | |||||
| statisticTime := beginTime | |||||
| currentTime := endTime | |||||
| for statisticTime.Before(currentTime) || statisticTime.Equal(currentTime) { | |||||
| countEach := summaryDurationStat(statisticTime) | |||||
| count += countEach | |||||
| statisticTime = statisticTime.Add(+1 * time.Hour) | |||||
| } | |||||
| return count | |||||
| } | |||||
| m, _ := time.ParseDuration("-1h") | |||||
| beginTime := currentTime.Add(m).Unix() | |||||
| endTime := currentTime.Unix() | |||||
| hourTime := currentTime.Add(m).Hour() | |||||
| //statisticTime是当前的时辰,比如当前是2019-01-01 12:01:01,那么statisticTime就是2019-01-01 12:00:00 | |||||
| func summaryDurationStat(statisticTime time.Time) int64 { | |||||
| var count int64 | |||||
| dateTime := timeutil.TimeStamp(statisticTime.Add(-1 * time.Hour).Unix()) | |||||
| beginTime := statisticTime.Add(-1 * time.Hour).Unix() | |||||
| dayTime := statisticTime.Add(-1 * time.Hour).Format("2006-01-02") | |||||
| hourTime := statisticTime.Add(-1 * time.Hour).Hour() | |||||
| endTime := statisticTime.Unix() | |||||
| ciTasks, err := models.GetCloudbrainByTime(beginTime, endTime) | ciTasks, err := models.GetCloudbrainByTime(beginTime, endTime) | ||||
| if err != nil { | if err != nil { | ||||
| log.Info("GetCloudbrainByTime err: %v", err) | log.Info("GetCloudbrainByTime err: %v", err) | ||||
| return | |||||
| return 0 | |||||
| } | } | ||||
| specMap := make(map[string]*models.Specification) | |||||
| cloudbrainMap := make(map[string]*models.Cloudbrain) | |||||
| models.LoadSpecs4CloudbrainInfo(ciTasks) | models.LoadSpecs4CloudbrainInfo(ciTasks) | ||||
| for _, cloudbrain := range 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 | |||||
| if cloudbrain.Cloudbrain.StartTime == 0 { | |||||
| cloudbrain.Cloudbrain.StartTime = cloudbrain.Cloudbrain.CreatedUnix | |||||
| } | |||||
| if cloudbrain.Cloudbrain.EndTime == 0 { | |||||
| cloudbrain.Cloudbrain.EndTime = cloudbrain.Cloudbrain.UpdatedUnix | |||||
| } | |||||
| cloudbrain = cloudbrainService.UpdateCloudbrainAiCenter(cloudbrain) | |||||
| if cloudbrain.Cloudbrain.Spec != nil { | |||||
| if _, ok := cloudbrainMap[cloudbrain.Cloudbrain.AiCenter+"/"+cloudbrain.Cloudbrain.Spec.AccCardType]; !ok { | |||||
| if cloudbrain.Cloudbrain.Spec != nil { | |||||
| cloudbrainMap[cloudbrain.Cloudbrain.AiCenter+"/"+cloudbrain.Cloudbrain.Spec.AccCardType] = &cloudbrain.Cloudbrain | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -42,69 +91,83 @@ func CloudbrainDurationStatisticHour() { | |||||
| resourceQueues, err := models.GetCanUseCardInfo() | resourceQueues, err := models.GetCanUseCardInfo() | ||||
| if err != nil { | if err != nil { | ||||
| log.Info("GetCanUseCardInfo err: %v", err) | log.Info("GetCanUseCardInfo err: %v", err) | ||||
| return | |||||
| return 0 | |||||
| } | } | ||||
| cardsTotalDurationMap := make(map[string]int) | cardsTotalDurationMap := make(map[string]int) | ||||
| for _, resourceQueue := range resourceQueues { | for _, resourceQueue := range resourceQueues { | ||||
| cardsTotalDurationMap[resourceQueue.Cluster+"/"+resourceQueue.AiCenterName+"/"+resourceQueue.AiCenterCode+"/"+resourceQueue.AccCardType+"/"+resourceQueue.ComputeResource] = resourceQueue.CardsTotalNum * 1 * 60 * 60 | |||||
| if _, ok := cardsTotalDurationMap[resourceQueue.Cluster+"/"+resourceQueue.AiCenterCode+"/"+resourceQueue.AccCardType]; !ok { | |||||
| cardsTotalDurationMap[resourceQueue.Cluster+"/"+resourceQueue.AiCenterCode+"/"+resourceQueue.AccCardType] = resourceQueue.CardsTotalNum * 1 * 60 * 60 | |||||
| } else { | |||||
| cardsTotalDurationMap[resourceQueue.Cluster+"/"+resourceQueue.AiCenterCode+"/"+resourceQueue.AccCardType] += 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 | |||||
| for centerCode, CardTypes := range cloudBrainCenterCodeAndCardTypeInfo { | |||||
| for cardType, cardDuration := range CardTypes { | |||||
| cloudbrainTable := cloudbrainMap[centerCode+"/"+cardType] | |||||
| if cloudbrainTable != nil { | |||||
| if _, ok := cardsTotalDurationMap[cloudbrainTable.Cluster+"/"+centerCode+"/"+cardType]; !ok { | |||||
| cardsTotalDurationMap[cloudbrainTable.Cluster+"/"+centerCode+"/"+cardType] = 0 | |||||
| } | } | ||||
| cloudbrainDurationStat := models.CloudbrainDurationStatistic{ | cloudbrainDurationStat := models.CloudbrainDurationStatistic{ | ||||
| DateTime: dateTime, | DateTime: dateTime, | ||||
| DayTime: dayTime, | DayTime: dayTime, | ||||
| HourTime: hourTime, | HourTime: hourTime, | ||||
| Cluster: spec.Cluster, | |||||
| AiCenterName: spec.AiCenterName, | |||||
| Cluster: cloudbrainTable.Cluster, | |||||
| AiCenterName: GetAiCenterNameByCode(centerCode, "zh-CN"), | |||||
| AiCenterCode: centerCode, | AiCenterCode: centerCode, | ||||
| AccCardType: cardType, | AccCardType: cardType, | ||||
| ComputeResource: spec.ComputeResource, | |||||
| CardsUseDuration: cardDuration, | CardsUseDuration: cardDuration, | ||||
| CardsTotalDuration: cardsTotalDurationMap[spec.Cluster+"/"+spec.AiCenterName+"/"+centerCode+"/"+cardType+"/"+spec.ComputeResource], | |||||
| CardsTotalDuration: cardsTotalDurationMap[cloudbrainTable.Cluster+"/"+centerCode+"/"+cardType], | |||||
| CreatedUnix: timeutil.TimeStampNow(), | CreatedUnix: timeutil.TimeStampNow(), | ||||
| } | } | ||||
| if _, err = models.InsertCloudbrainDurationStatistic(&cloudbrainDurationStat); err != nil { | if _, err = models.InsertCloudbrainDurationStatistic(&cloudbrainDurationStat); err != nil { | ||||
| log.Error("Insert cloudbrainDurationStat failed: %v", err.Error()) | log.Error("Insert cloudbrainDurationStat failed: %v", err.Error()) | ||||
| } | } | ||||
| delete(cardsTotalDurationMap, spec.Cluster+"/"+spec.AiCenterName+"/"+centerCode+"/"+cardType+"/"+spec.ComputeResource) | |||||
| count++ | |||||
| delete(cardsTotalDurationMap, cloudbrainTable.Cluster+"/"+centerCode+"/"+cardType) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| for key, cardsTotalDuration := range cardsTotalDurationMap { | 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{ | cloudbrainDurationStat := models.CloudbrainDurationStatistic{ | ||||
| DateTime: dateTime, | DateTime: dateTime, | ||||
| DayTime: dayTime, | DayTime: dayTime, | ||||
| HourTime: hourTime, | HourTime: hourTime, | ||||
| Cluster: strings.Split(key, "/")[0], | 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], | |||||
| AiCenterName: GetAiCenterNameByCode(strings.Split(key, "/")[1], "zh-CN"), | |||||
| AiCenterCode: strings.Split(key, "/")[1], | |||||
| AccCardType: strings.Split(key, "/")[2], | |||||
| CardsUseDuration: 0, | CardsUseDuration: 0, | ||||
| CardsTotalDuration: cardsTotalDuration, | CardsTotalDuration: cardsTotalDuration, | ||||
| CardsTotalNum: cardsTotalDuration / 1 / 60 / 60, | |||||
| CreatedUnix: timeutil.TimeStampNow(), | CreatedUnix: timeutil.TimeStampNow(), | ||||
| } | } | ||||
| if _, err = models.InsertCloudbrainDurationStatistic(&cloudbrainDurationStat); err != nil { | if _, err = models.InsertCloudbrainDurationStatistic(&cloudbrainDurationStat); err != nil { | ||||
| log.Error("Insert cloudbrainDurationStat failed: %v", err.Error()) | log.Error("Insert cloudbrainDurationStat failed: %v", err.Error()) | ||||
| } | } | ||||
| count++ | |||||
| } | } | ||||
| log.Info("finish summary cloudbrainDurationStat") | log.Info("finish summary cloudbrainDurationStat") | ||||
| return count | |||||
| } | |||||
| func GetAiCenterNameByCode(centerCode string, language string) string { | |||||
| var aiCenterName string | |||||
| aiCenterInfo := cloudbrainService.GetAiCenterInfoByCenterCode(centerCode) | |||||
| if aiCenterInfo != nil { | |||||
| if language == "zh-CN" { | |||||
| aiCenterName = aiCenterInfo.Content | |||||
| } else { | |||||
| aiCenterName = aiCenterInfo.ContentEN | |||||
| } | |||||
| } else { | |||||
| aiCenterName = centerCode | |||||
| } | |||||
| return aiCenterName | |||||
| } | } | ||||
| func getcloudBrainCenterCodeAndCardTypeInfo(ciTasks []*models.CloudbrainInfo, beginTime int64, endTime int64) map[string]map[string]int { | func getcloudBrainCenterCodeAndCardTypeInfo(ciTasks []*models.CloudbrainInfo, beginTime int64, endTime int64) map[string]map[string]int { | ||||
| @@ -112,7 +175,7 @@ func getcloudBrainCenterCodeAndCardTypeInfo(ciTasks []*models.CloudbrainInfo, be | |||||
| var AccCardsNum int | var AccCardsNum int | ||||
| cloudBrainCenterCodeAndCardType := make(map[string]map[string]int) | cloudBrainCenterCodeAndCardType := make(map[string]map[string]int) | ||||
| for _, cloudbrain := range ciTasks { | for _, cloudbrain := range ciTasks { | ||||
| cloudbrain = cloudbrainService.UpdateCloudbrainAiCenter(cloudbrain) | |||||
| if cloudbrain.Cloudbrain.StartTime == 0 { | if cloudbrain.Cloudbrain.StartTime == 0 { | ||||
| cloudbrain.Cloudbrain.StartTime = cloudbrain.Cloudbrain.CreatedUnix | cloudbrain.Cloudbrain.StartTime = cloudbrain.Cloudbrain.CreatedUnix | ||||
| } | } | ||||
| @@ -129,41 +192,70 @@ func getcloudBrainCenterCodeAndCardTypeInfo(ciTasks []*models.CloudbrainInfo, be | |||||
| } else { | } else { | ||||
| AccCardsNum = cloudbrain.Cloudbrain.Spec.AccCardsNum | AccCardsNum = cloudbrain.Cloudbrain.Spec.AccCardsNum | ||||
| } | } | ||||
| if _, ok := cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode]; !ok { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode] = make(map[string]int) | |||||
| if _, ok := cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter]; !ok { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter] = 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)) | |||||
| if cloudbrain.Cloudbrain.Spec != nil { | |||||
| if cloudbrain.Cloudbrain.Status == string(models.ModelArtsRunning) { | |||||
| if _, ok := cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType]; !ok { | |||||
| if int64(cloudbrain.Cloudbrain.StartTime) < beginTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(endTime) - int(beginTime)) | |||||
| } else if beginTime <= int64(cloudbrain.Cloudbrain.StartTime) && int64(cloudbrain.Cloudbrain.StartTime) < endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(endTime) - int(cloudbrain.Cloudbrain.StartTime)) | |||||
| } else if int64(cloudbrain.Cloudbrain.StartTime) >= endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] = 0 | |||||
| } | |||||
| } else { | } else { | ||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(endTime) - int(cloudbrain.Cloudbrain.StartTime)) | |||||
| if int64(cloudbrain.Cloudbrain.StartTime) < beginTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(endTime) - int(beginTime)) | |||||
| } else if beginTime <= int64(cloudbrain.Cloudbrain.StartTime) && int64(cloudbrain.Cloudbrain.StartTime) < endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(endTime) - int(cloudbrain.Cloudbrain.StartTime)) | |||||
| } else if int64(cloudbrain.Cloudbrain.StartTime) >= endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] += 0 | |||||
| } | |||||
| } | } | ||||
| } else { | } else { | ||||
| if int64(cloudbrain.Cloudbrain.StartTime) < beginTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(endTime) - int(beginTime)) | |||||
| if _, ok := cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType]; !ok { | |||||
| if int64(cloudbrain.Cloudbrain.StartTime) <= beginTime && int64(cloudbrain.Cloudbrain.EndTime) <= endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(cloudbrain.Cloudbrain.EndTime) - int(beginTime)) | |||||
| } else if int64(cloudbrain.Cloudbrain.StartTime) <= beginTime && int64(cloudbrain.Cloudbrain.EndTime) > endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(endTime) - int(beginTime)) | |||||
| } else if beginTime <= int64(cloudbrain.Cloudbrain.StartTime) && int64(cloudbrain.Cloudbrain.StartTime) <= endTime && int64(cloudbrain.Cloudbrain.EndTime) <= endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(cloudbrain.Cloudbrain.EndTime) - int(cloudbrain.Cloudbrain.StartTime)) | |||||
| } else if beginTime <= int64(cloudbrain.Cloudbrain.StartTime) && int64(cloudbrain.Cloudbrain.StartTime) <= endTime && int64(cloudbrain.Cloudbrain.EndTime) > endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(endTime) - int(cloudbrain.Cloudbrain.StartTime)) | |||||
| } | |||||
| } else { | } else { | ||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(endTime) - int(cloudbrain.Cloudbrain.StartTime)) | |||||
| if int64(cloudbrain.Cloudbrain.StartTime) <= beginTime && int64(cloudbrain.Cloudbrain.EndTime) <= endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(cloudbrain.Cloudbrain.EndTime) - int(beginTime)) | |||||
| } else if int64(cloudbrain.Cloudbrain.StartTime) <= beginTime && int64(cloudbrain.Cloudbrain.EndTime) > endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(endTime) - int(beginTime)) | |||||
| } else if beginTime <= int64(cloudbrain.Cloudbrain.StartTime) && int64(cloudbrain.Cloudbrain.StartTime) <= endTime && int64(cloudbrain.Cloudbrain.EndTime) <= endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(cloudbrain.Cloudbrain.EndTime) - int(cloudbrain.Cloudbrain.StartTime)) | |||||
| } else if beginTime <= int64(cloudbrain.Cloudbrain.StartTime) && int64(cloudbrain.Cloudbrain.StartTime) <= endTime && int64(cloudbrain.Cloudbrain.EndTime) > endTime { | |||||
| cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.AiCenter][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 | return cloudBrainCenterCodeAndCardType | ||||
| } | } | ||||
| func CloudbrainUpdateHistoryData(ctx *context.Context) { | |||||
| beginTimeStr := ctx.QueryTrim("beginTime") | |||||
| endTimeStr := ctx.QueryTrim("endTime") | |||||
| beginTime, _ := time.ParseInLocation("2006-01-02 15:04:05", beginTimeStr, time.Local) | |||||
| endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", endTimeStr, time.Local) | |||||
| beginTimeUnix := timeutil.TimeStamp(beginTime.Unix()) | |||||
| endTimeUnix := timeutil.TimeStamp(endTime.Unix()) | |||||
| err := models.DeleteCloudbrainDurationStatistic(beginTimeUnix, endTimeUnix) | |||||
| count := UpdateDurationStatisticHistoryData(beginTime, endTime) | |||||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||||
| "message": 0, | |||||
| "count": count, | |||||
| "err": err, | |||||
| }) | |||||
| } | |||||
| @@ -1,7 +1,6 @@ | |||||
| package repo | package repo | ||||
| import ( | import ( | ||||
| "code.gitea.io/gitea/modules/urfs_client/urchin" | |||||
| "encoding/json" | "encoding/json" | ||||
| "errors" | "errors" | ||||
| "fmt" | "fmt" | ||||
| @@ -12,6 +11,9 @@ import ( | |||||
| "strconv" | "strconv" | ||||
| "strings" | "strings" | ||||
| "code.gitea.io/gitea/modules/urfs_client/urchin" | |||||
| "code.gitea.io/gitea/routers/response" | |||||
| "code.gitea.io/gitea/services/cloudbrain/cloudbrainTask" | "code.gitea.io/gitea/services/cloudbrain/cloudbrainTask" | ||||
| "code.gitea.io/gitea/modules/dataset" | "code.gitea.io/gitea/modules/dataset" | ||||
| @@ -861,10 +863,10 @@ func GrampusTrainJobShow(ctx *context.Context) { | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| err = models.UpdateJob(task) | |||||
| if err != nil { | |||||
| log.Error("UpdateJob failed:" + err.Error()) | |||||
| } | |||||
| } | |||||
| err = models.UpdateJob(task) | |||||
| if err != nil { | |||||
| log.Error("UpdateJob failed:" + err.Error()) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -936,15 +938,14 @@ func GrampusGetLog(ctx *context.Context) { | |||||
| content, err := grampus.GetTrainJobLog(job.JobID) | content, err := grampus.GetTrainJobLog(job.JobID) | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("GetTrainJobLog failed: %v", err, ctx.Data["MsgID"]) | log.Error("GetTrainJobLog failed: %v", err, ctx.Data["MsgID"]) | ||||
| ctx.ServerError(err.Error(), err) | |||||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||||
| "JobName": job.JobName, | |||||
| "Content": "", | |||||
| "CanLogDownload": false, | |||||
| }) | |||||
| return | return | ||||
| } | } | ||||
| var canLogDownload bool | |||||
| if err != nil { | |||||
| canLogDownload = false | |||||
| } else { | |||||
| canLogDownload = true | |||||
| } | |||||
| canLogDownload := err == nil && job.IsUserHasRight(ctx.User) | |||||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | ctx.JSON(http.StatusOK, map[string]interface{}{ | ||||
| "JobName": job.JobName, | "JobName": job.JobName, | ||||
| "Content": content, | "Content": content, | ||||
| @@ -954,6 +955,28 @@ func GrampusGetLog(ctx *context.Context) { | |||||
| return | return | ||||
| } | } | ||||
| func GrampusMetrics(ctx *context.Context) { | |||||
| jobID := ctx.Params(":jobid") | |||||
| job, err := models.GetCloudbrainByJobID(jobID) | |||||
| if err != nil { | |||||
| log.Error("GetCloudbrainByJobID failed: %v", err, ctx.Data["MsgID"]) | |||||
| ctx.ServerError(err.Error(), err) | |||||
| return | |||||
| } | |||||
| result, err := grampus.GetGrampusMetrics(job.JobID) | |||||
| if err != nil { | |||||
| log.Error("GetTrainJobLog failed: %v", err, ctx.Data["MsgID"]) | |||||
| } | |||||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||||
| "JobID": jobID, | |||||
| "Interval": result.Interval, | |||||
| "MetricsInfo": result.MetricsInfo, | |||||
| }) | |||||
| return | |||||
| } | |||||
| func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bootFile, paramSrc, outputRemotePath, datasetName, pretrainModelPath, pretrainModelFileName, modelRemoteObsUrl string) (string, error) { | func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bootFile, paramSrc, outputRemotePath, datasetName, pretrainModelPath, pretrainModelFileName, modelRemoteObsUrl string) (string, error) { | ||||
| var command string | var command string | ||||
| @@ -1100,3 +1123,38 @@ func downloadZipCode(ctx *context.Context, codePath, branchName string) error { | |||||
| return nil | return nil | ||||
| } | } | ||||
| func HandleTaskWithAiCenter(ctx *context.Context) { | |||||
| log.Info("HandleTaskWithAiCenter start") | |||||
| updateCounts := 0 | |||||
| cloudBrains, err := models.GetC2NetWithAiCenterWrongJob() | |||||
| if err != nil { | |||||
| log.Error("GetC2NetWithAiCenterWrongJob failed:" + err.Error()) | |||||
| return | |||||
| } | |||||
| if len(cloudBrains) == 0 { | |||||
| log.Info("HandleC2NetWithAiCenterWrongJob:no task need handle") | |||||
| return | |||||
| } | |||||
| cloudBrainCounts := len(cloudBrains) | |||||
| for _, task := range cloudBrains { | |||||
| result, err := grampus.GetJob(task.JobID) | |||||
| if err != nil { | |||||
| log.Error("GetJob failed:" + err.Error()) | |||||
| continue | |||||
| } | |||||
| if len(result.JobInfo.Tasks) != 0 { | |||||
| if len(result.JobInfo.Tasks[0].CenterID) == 1 && len(result.JobInfo.Tasks[0].CenterName) == 1 { | |||||
| task.AiCenter = result.JobInfo.Tasks[0].CenterID[0] + "+" + result.JobInfo.Tasks[0].CenterName[0] | |||||
| } | |||||
| err = models.UpdateJob(task) | |||||
| if err != nil { | |||||
| log.Error("UpdateJob failed:" + err.Error()) | |||||
| } | |||||
| updateCounts++ | |||||
| } | |||||
| } | |||||
| r := make(map[string]interface{}, 0) | |||||
| r["cloudBrainCounts"] = cloudBrainCounts | |||||
| r["updateCounts"] = updateCounts | |||||
| ctx.JSON(http.StatusOK, response.SuccessWithData(r)) | |||||
| } | |||||
| @@ -645,6 +645,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Group("/specification", func() { | m.Group("/specification", func() { | ||||
| m.Get("", admin.GetSpecificationPage) | m.Get("", admin.GetSpecificationPage) | ||||
| m.Get("/list", admin.GetResourceSpecificationList) | m.Get("/list", admin.GetResourceSpecificationList) | ||||
| m.Get("/list/all", admin.GetAllResourceSpecificationList) | |||||
| m.Get("/scenes/:id", admin.GetResourceSpecificationScenes) | m.Get("/scenes/:id", admin.GetResourceSpecificationScenes) | ||||
| m.Post("/grampus/sync", admin.SyncGrampusSpecs) | m.Post("/grampus/sync", admin.SyncGrampusSpecs) | ||||
| m.Post("/add", binding.Bind(models.ResourceSpecificationReq{}), admin.AddResourceSpecification) | m.Post("/add", binding.Bind(models.ResourceSpecificationReq{}), admin.AddResourceSpecification) | ||||
| @@ -728,6 +729,13 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Post("/complete_multipart", repo.CompleteMultipart) | m.Post("/complete_multipart", repo.CompleteMultipart) | ||||
| }) | }) | ||||
| m.Group("/attachments/model", func() { | |||||
| m.Get("/get_chunks", repo.GetModelChunks) | |||||
| m.Get("/new_multipart", repo.NewModelMultipart) | |||||
| m.Get("/get_multipart_url", repo.GetModelMultipartUploadUrl) | |||||
| m.Post("/complete_multipart", repo.CompleteModelMultipart) | |||||
| }) | |||||
| m.Group("/attachments", func() { | m.Group("/attachments", func() { | ||||
| m.Get("/public/query", repo.QueryAllPublicDataset) | m.Get("/public/query", repo.QueryAllPublicDataset) | ||||
| m.Get("/private/:username", repo.QueryPrivateDataset) | m.Get("/private/:username", repo.QueryPrivateDataset) | ||||
| @@ -1228,6 +1236,12 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| }) | }) | ||||
| }, context.RepoRef()) | }, context.RepoRef()) | ||||
| m.Group("/modelmanage", func() { | m.Group("/modelmanage", func() { | ||||
| m.Get("/create_local_model_1", repo.CreateLocalModel) | |||||
| m.Get("/create_local_model_2", repo.CreateLocalModelForUpload) | |||||
| m.Get("/create_online_model", repo.CreateOnlineModel) | |||||
| m.Post("/create_local_model", repo.SaveLocalModel) | |||||
| m.Delete("/delete_model_file", repo.DeleteModelFile) | |||||
| m.Post("/create_model", repo.SaveModel) | m.Post("/create_model", repo.SaveModel) | ||||
| m.Post("/create_model_convert", reqWechatBind, reqRepoModelManageWriter, repo.SaveModelConvert) | m.Post("/create_model_convert", reqWechatBind, reqRepoModelManageWriter, repo.SaveModelConvert) | ||||
| m.Post("/create_new_model", repo.SaveNewNameModel) | m.Post("/create_new_model", repo.SaveNewNameModel) | ||||
| @@ -1487,6 +1501,12 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Get("/record/list", point.GetPointRecordList) | m.Get("/record/list", point.GetPointRecordList) | ||||
| }, reqSignIn) | }, reqSignIn) | ||||
| m.Group("/resources", func() { | |||||
| m.Group("/queue", func() { | |||||
| m.Get("/centers", admin.GetResourceAiCenters) | |||||
| }) | |||||
| }) | |||||
| if setting.API.EnableSwagger { | if setting.API.EnableSwagger { | ||||
| m.Get("/swagger.v1.json", templates.JSONRenderer(), routers.SwaggerV1Json) | m.Get("/swagger.v1.json", templates.JSONRenderer(), routers.SwaggerV1Json) | ||||
| } | } | ||||
| @@ -23,6 +23,8 @@ import ( | |||||
| "code.gitea.io/gitea/modules/modelarts" | "code.gitea.io/gitea/modules/modelarts" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
| "code.gitea.io/gitea/routers/repo" | |||||
| cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||||
| issue_service "code.gitea.io/gitea/services/issue" | issue_service "code.gitea.io/gitea/services/issue" | ||||
| pull_service "code.gitea.io/gitea/services/pull" | pull_service "code.gitea.io/gitea/services/pull" | ||||
| @@ -837,6 +839,8 @@ func Cloudbrains(ctx *context.Context) { | |||||
| } | } | ||||
| models.LoadSpecs4CloudbrainInfo(ciTasks) | models.LoadSpecs4CloudbrainInfo(ciTasks) | ||||
| for i, _ := range ciTasks { | for i, _ := range ciTasks { | ||||
| ciTasks[i] = cloudbrainService.UpdateCloudbrainAiCenter(ciTasks[i]) | |||||
| ciTasks[i].Cloudbrain.AiCenter = repo.GetAiCenterNameByCode(ciTasks[i].Cloudbrain.AiCenter, ctx.Language()) | |||||
| ciTasks[i].CanDebug = true | ciTasks[i].CanDebug = true | ||||
| ciTasks[i].CanDel = true | ciTasks[i].CanDel = true | ||||
| ciTasks[i].Cloudbrain.ComputeResource = ciTasks[i].ComputeResource | ciTasks[i].Cloudbrain.ComputeResource = ciTasks[i].ComputeResource | ||||
| @@ -14,7 +14,7 @@ import ( | |||||
| var noteBookOKMap = make(map[int64]int, 20) | var noteBookOKMap = make(map[int64]int, 20) | ||||
| //if a task notebook url can get two times, the notebook can browser. | //if a task notebook url can get two times, the notebook can browser. | ||||
| const successfulCount = 2 | |||||
| const successfulCount = 3 | |||||
| func SyncCloudBrainOneStatus(task *models.Cloudbrain) (*models.Cloudbrain, error) { | func SyncCloudBrainOneStatus(task *models.Cloudbrain) (*models.Cloudbrain, error) { | ||||
| jobResult, err := cloudbrain.GetJob(task.JobID) | jobResult, err := cloudbrain.GetJob(task.JobID) | ||||
| @@ -16,7 +16,7 @@ func AddResourceQueue(req models.ResourceQueueReq) error { | |||||
| } | } | ||||
| func UpdateResourceQueue(queueId int64, req models.ResourceQueueReq) error { | func UpdateResourceQueue(queueId int64, req models.ResourceQueueReq) error { | ||||
| if _, err := models.UpdateResourceQueueById(queueId, models.ResourceQueue{ | |||||
| if _, err := models.UpdateResourceCardsTotalNum(queueId, models.ResourceQueue{ | |||||
| CardsTotalNum: req.CardsTotalNum, | CardsTotalNum: req.CardsTotalNum, | ||||
| Remark: req.Remark, | Remark: req.Remark, | ||||
| }); err != nil { | }); err != nil { | ||||
| @@ -130,10 +130,49 @@ func GetResourceSpecificationList(opts models.SearchResourceSpecificationOptions | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| return models.NewResourceSpecAndQueueListRes(n, r), nil | return models.NewResourceSpecAndQueueListRes(n, r), nil | ||||
| } | } | ||||
| //GetAllDistinctResourceSpecification returns specification and queue after distinct | |||||
| //totalSize is always 0 here | |||||
| func GetAllDistinctResourceSpecification(opts models.SearchResourceSpecificationOptions) (*models.ResourceSpecAndQueueListRes, error) { | |||||
| opts.Page = 0 | |||||
| opts.PageSize = 1000 | |||||
| opts.OrderBy = models.SearchSpecOrder4Standard | |||||
| _, r, err := models.SearchResourceSpecification(opts) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| nr := distinctResourceSpecAndQueue(r) | |||||
| return models.NewResourceSpecAndQueueListRes(0, nr), nil | |||||
| } | |||||
| func distinctResourceSpecAndQueue(r []models.ResourceSpecAndQueue) []models.ResourceSpecAndQueue { | |||||
| specs := make([]models.ResourceSpecAndQueue, 0, len(r)) | |||||
| sourceSpecIdMap := make(map[string]models.ResourceSpecAndQueue, 0) | |||||
| for i := 0; i < len(r); i++ { | |||||
| spec := r[i] | |||||
| if spec.SourceSpecId == "" { | |||||
| specs = append(specs, spec) | |||||
| continue | |||||
| } | |||||
| if _, has := sourceSpecIdMap[spec.SourceSpecId]; has { | |||||
| //prefer to use on-shelf spec | |||||
| if sourceSpecIdMap[spec.SourceSpecId].Status != spec.Status && spec.Status == models.SpecOnShelf { | |||||
| for k, v := range specs { | |||||
| if v.ResourceSpecification.ID == sourceSpecIdMap[spec.SourceSpecId].ResourceSpecification.ID { | |||||
| specs[k] = spec | |||||
| } | |||||
| } | |||||
| } | |||||
| continue | |||||
| } | |||||
| specs = append(specs, spec) | |||||
| sourceSpecIdMap[spec.SourceSpecId] = spec | |||||
| } | |||||
| return specs | |||||
| } | |||||
| func GetResourceSpecificationScenes(specId int64) ([]models.ResourceSceneBriefRes, error) { | func GetResourceSpecificationScenes(specId int64) ([]models.ResourceSceneBriefRes, error) { | ||||
| r, err := models.GetSpecScenes(specId) | r, err := models.GetSpecScenes(specId) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -200,6 +239,7 @@ func AddSpecOperateLog(doerId int64, operateType string, newValue, oldValue *mod | |||||
| } | } | ||||
| func FindAvailableSpecs(userId int64, opts models.FindSpecsOptions) ([]*models.Specification, error) { | func FindAvailableSpecs(userId int64, opts models.FindSpecsOptions) ([]*models.Specification, error) { | ||||
| opts.SpecStatus = models.SpecOnShelf | |||||
| r, err := models.FindSpecs(opts) | r, err := models.FindSpecs(opts) | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("FindAvailableSpecs error.%v", err) | log.Error("FindAvailableSpecs error.%v", err) | ||||
| @@ -6,6 +6,8 @@ import ( | |||||
| "strings" | "strings" | ||||
| "time" | "time" | ||||
| "code.gitea.io/gitea/models" | |||||
| "code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| ) | ) | ||||
| @@ -34,6 +36,7 @@ func GetAiCenterShow(aiCenter string, ctx *context.Context) string { | |||||
| return "" | return "" | ||||
| } | } | ||||
| func GetDisplayJobName(username string) string { | func GetDisplayJobName(username string) string { | ||||
| t := time.Now() | t := time.Now() | ||||
| return jobNamePrefixValid(cutString(username, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | return jobNamePrefixValid(cutString(username, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | ||||
| @@ -54,5 +57,42 @@ func jobNamePrefixValid(s string) string { | |||||
| re = regexp.MustCompile(`^[_\\-]+`) | re = regexp.MustCompile(`^[_\\-]+`) | ||||
| return re.ReplaceAllString(removeSpecial, "") | return re.ReplaceAllString(removeSpecial, "") | ||||
| } | |||||
| func GetAiCenterInfoByCenterCode(aiCenterCode string) *setting.C2NetSequenceInfo { | |||||
| if setting.AiCenterCodeAndNameMapInfo != nil { | |||||
| if info, ok := setting.AiCenterCodeAndNameMapInfo[aiCenterCode]; ok { | |||||
| return info | |||||
| } else { | |||||
| return nil | |||||
| } | |||||
| } else { | |||||
| return nil | |||||
| } | |||||
| } | |||||
| func getAiCenterCode(aiCenter string) string { | |||||
| aiCenterInfo := strings.Split(aiCenter, "+") | |||||
| return aiCenterInfo[0] | |||||
| } | |||||
| func UpdateCloudbrainAiCenter(cloudbrain *models.CloudbrainInfo) *models.CloudbrainInfo { | |||||
| if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainOne { | |||||
| cloudbrain.Cloudbrain.AiCenter = models.AICenterOfCloudBrainOne | |||||
| cloudbrain.Cloudbrain.Cluster = models.OpenICluster | |||||
| } | |||||
| if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainTwo { | |||||
| cloudbrain.Cloudbrain.AiCenter = models.AICenterOfCloudBrainTwo | |||||
| cloudbrain.Cloudbrain.Cluster = models.OpenICluster | |||||
| } | |||||
| if cloudbrain.Cloudbrain.Type == models.TypeCDCenter { | |||||
| cloudbrain.Cloudbrain.AiCenter = models.AICenterOfChengdu | |||||
| cloudbrain.Cloudbrain.Cluster = models.OpenICluster | |||||
| } | |||||
| if cloudbrain.Cloudbrain.Type == models.TypeC2Net { | |||||
| cloudbrain.Cloudbrain.AiCenter = getAiCenterCode(cloudbrain.Cloudbrain.AiCenter) | |||||
| cloudbrain.Cloudbrain.Cluster = models.C2NetCluster | |||||
| } | |||||
| return cloudbrain | |||||
| } | } | ||||
| @@ -170,7 +170,7 @@ | |||||
| </div> | </div> | ||||
| <!-- 智算中心 --> | <!-- 智算中心 --> | ||||
| <div class="one wide column text center nowrap" style="width:8% !important;"> | <div class="one wide column text center nowrap" style="width:8% !important;"> | ||||
| <span style="font-size: 12px;" class="aicenter_{{.DisplayJobName}}_{{$JobID}}">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span> | |||||
| <span style="font-size: 12px;" class="aicenter_{{.DisplayJobName}}_{{$JobID}}" title="{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span> | |||||
| </div> | </div> | ||||
| <!-- XPU类型 --> | <!-- XPU类型 --> | ||||
| <div class="one wide column text center nowrap" style="width:8% !important;"> | <div class="one wide column text center nowrap" style="width:8% !important;"> | ||||
| @@ -184,16 +184,16 @@ | |||||
| spanEl.setAttribute('title', cardType); | spanEl.setAttribute('title', cardType); | ||||
| spanEl.innerText = cardType; | spanEl.innerText = cardType; | ||||
| var cluster = spec.Cluster || '--'; | |||||
| var cluster = {{.Cluster}} || '--'; | |||||
| var clusterName = document.querySelector('.cloudbrain_debug').dataset['cluster' + cluster[0] + cluster.toLocaleLowerCase().slice(1)] || '--'; | var clusterName = document.querySelector('.cloudbrain_debug').dataset['cluster' + cluster[0] + cluster.toLocaleLowerCase().slice(1)] || '--'; | ||||
| spanEl = document.querySelector('.cluster_{{.DisplayJobName}}_{{$JobID}}'); | spanEl = document.querySelector('.cluster_{{.DisplayJobName}}_{{$JobID}}'); | ||||
| spanEl.setAttribute('title', cluster); | spanEl.setAttribute('title', cluster); | ||||
| spanEl.innerText = clusterName; | spanEl.innerText = clusterName; | ||||
| var aiCenter = spec.AiCenterName || '--'; | |||||
| spanEl = document.querySelector('.aicenter_{{.DisplayJobName}}_{{$JobID}}'); | |||||
| spanEl.setAttribute('title', aiCenter); | |||||
| spanEl.innerText = aiCenter; | |||||
| // var aiCenter = spec.AiCenterName || '--'; | |||||
| // spanEl = document.querySelector('.aicenter_{{.DisplayJobName}}_{{$JobID}}'); | |||||
| // spanEl.setAttribute('title', aiCenter); | |||||
| // spanEl.innerText = aiCenter; | |||||
| })(); | })(); | ||||
| </script> | </script> | ||||
| <!-- 创建者 --> | <!-- 创建者 --> | ||||
| @@ -71,22 +71,20 @@ | |||||
| document.addEventListener('DOMContentLoaded', function() { | document.addEventListener('DOMContentLoaded', function() { | ||||
| $.ajax({ | $.ajax({ | ||||
| type: "GET", | type: "GET", | ||||
| url: "/api/v1/cloudbrain/get_center_info", | |||||
| url: "/api/v1/cloudbrainboard/cloudbrain/resource_queues", | |||||
| dataType: "json", | dataType: "json", | ||||
| data: {}, | data: {}, | ||||
| success: function (res) { | success: function (res) { | ||||
| var data = res || []; | |||||
| var data = res.resourceQueues || []; | |||||
| var aiCenterSelEl = $('#aiCenter-sel'); | var aiCenterSelEl = $('#aiCenter-sel'); | ||||
| var itemEl = aiCenterSelEl.find('.menu .item').eq(0); | var itemEl = aiCenterSelEl.find('.menu .item').eq(0); | ||||
| var selectAiCenterCode = aiCenterSelEl.find('.default').attr('aicenter'); | var selectAiCenterCode = aiCenterSelEl.find('.default').attr('aicenter'); | ||||
| var selectAiCenterName = ''; | var selectAiCenterName = ''; | ||||
| var lang = document.querySelector('html').getAttribute('lang') || 'en-US'; | var lang = document.querySelector('html').getAttribute('lang') || 'en-US'; | ||||
| var except = ['', 'more']; | |||||
| for (var i = 0, iLen = data.length; i < iLen; i++) { | for (var i = 0, iLen = data.length; i < iLen; i++) { | ||||
| var dataI = data[i]; | var dataI = data[i]; | ||||
| var aiCenterCode = dataI.name; | |||||
| if (except.indexOf(aiCenterCode) >= 0) continue; | |||||
| var aiCenterName = lang === 'en-US' ? dataI.content_en : dataI.content; | |||||
| var aiCenterCode = dataI.AiCenterCode; | |||||
| var aiCenterName = dataI.AiCenterName; | |||||
| var itemClone = itemEl.clone(); | var itemClone = itemEl.clone(); | ||||
| var oHref = itemClone.attr('href'); | var oHref = itemClone.attr('href'); | ||||
| var oId = itemClone.attr('id'); | var oId = itemClone.attr('id'); | ||||
| @@ -85,22 +85,20 @@ | |||||
| document.addEventListener('DOMContentLoaded', function() { | document.addEventListener('DOMContentLoaded', function() { | ||||
| $.ajax({ | $.ajax({ | ||||
| type: "GET", | type: "GET", | ||||
| url: "/api/v1/cloudbrain/get_center_info", | |||||
| url: "/api/v1/cloudbrainboard/cloudbrain/resource_queues", | |||||
| dataType: "json", | dataType: "json", | ||||
| data: {}, | data: {}, | ||||
| success: function (res) { | success: function (res) { | ||||
| var data = res || []; | |||||
| var data = res.resourceQueues || []; | |||||
| var aiCenterSelEl = $('#aiCenter-sel'); | var aiCenterSelEl = $('#aiCenter-sel'); | ||||
| var itemEl = aiCenterSelEl.find('.menu .item').eq(0); | var itemEl = aiCenterSelEl.find('.menu .item').eq(0); | ||||
| var selectAiCenterCode = aiCenterSelEl.find('.default').attr('aicenter'); | var selectAiCenterCode = aiCenterSelEl.find('.default').attr('aicenter'); | ||||
| var selectAiCenterName = ''; | var selectAiCenterName = ''; | ||||
| var lang = document.querySelector('html').getAttribute('lang') || 'en-US'; | var lang = document.querySelector('html').getAttribute('lang') || 'en-US'; | ||||
| var except = ['', 'more']; | |||||
| for (var i = 0, iLen = data.length; i < iLen; i++) { | for (var i = 0, iLen = data.length; i < iLen; i++) { | ||||
| var dataI = data[i]; | var dataI = data[i]; | ||||
| var aiCenterCode = dataI.name; | |||||
| if (except.indexOf(aiCenterCode) >= 0) continue; | |||||
| var aiCenterName = lang === 'en-US' ? dataI.content_en : dataI.content; | |||||
| var aiCenterCode = dataI.AiCenterCode; | |||||
| var aiCenterName = dataI.AiCenterName; | |||||
| var itemClone = itemEl.clone(); | var itemClone = itemEl.clone(); | ||||
| var oHref = itemClone.attr('href'); | var oHref = itemClone.attr('href'); | ||||
| var oId = itemClone.attr('id'); | var oId = itemClone.attr('id'); | ||||
| @@ -24,11 +24,30 @@ | |||||
| <div class="text">{{.LangName}}</div> | <div class="text">{{.LangName}}</div> | ||||
| <div class="menu"> | <div class="menu"> | ||||
| {{range .AllLangs}} | {{range .AllLangs}} | ||||
| <a lang="{{.Lang}}" class="item {{if eq $.Lang .Lang}}active selected{{end}}" href="{{if eq $.Lang .Lang}}#{{else}}{{$.Link}}?lang={{.Lang}}{{end}}">{{.Name}}</a> | |||||
| <!-- <a lang="{{.Lang}}" class="item {{if eq $.Lang .Lang}}active selected{{end}}" href="{{if eq $.Lang .Lang}}#{{else}}{{$.Link}}?lang={{.Lang}}{{end}}">{{.Name}}</a> --> | |||||
| <a lang="{{.Lang}}" class="item {{if eq $.Lang .Lang}}active selected{{end}}" href="javascript:;" olang="{{$.Lang}}" lang="{{.Lang}}" >{{.Name}}</a> | |||||
| {{end}} | {{end}} | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <script> | |||||
| ;(function() { | |||||
| document.addEventListener('DOMContentLoaded', function() { | |||||
| $('.ui.language .menu .item').on('click', function() { | |||||
| var lang = $(this).attr('lang'); | |||||
| var oLang = $(this).attr('olang'); | |||||
| if (oLang === lang) return; | |||||
| var origin = window.location.origin; | |||||
| var pathname = window.location.pathname; | |||||
| var search = window.location.search; | |||||
| var hash = window.location.hash; | |||||
| var oHref = window.location.href; | |||||
| var urlSearchParams = new URLSearchParams(search); | |||||
| urlSearchParams.set('lang', lang); | |||||
| window.location.href = origin + pathname + '?' + urlSearchParams.toString() + hash; | |||||
| }); | |||||
| }); | |||||
| })(); | |||||
| </script> | |||||
| <a href="https://git.openi.org.cn/zeizei/OpenI_Learning" class="item" target="_blank"><i class="compass icon" ></i> {{.i18n.Tr "custom.Platform_Tutorial"}}</a> | <a href="https://git.openi.org.cn/zeizei/OpenI_Learning" class="item" target="_blank"><i class="compass icon" ></i> {{.i18n.Tr "custom.Platform_Tutorial"}}</a> | ||||
| {{if .EnableSwagger}}<a href="/api/swagger" class="item"><i class="plug icon"></i> API</a>{{end}} | {{if .EnableSwagger}}<a href="/api/swagger" class="item"><i class="plug icon"></i> API</a>{{end}} | ||||
| {{if .IsSigned}} | {{if .IsSigned}} | ||||
| @@ -22,10 +22,30 @@ | |||||
| <div class="text">{{.LangName}}</div> | <div class="text">{{.LangName}}</div> | ||||
| <div class="menu"> | <div class="menu"> | ||||
| {{range .AllLangs}} | {{range .AllLangs}} | ||||
| <a lang="{{.Lang}}" class="item {{if eq $.Lang .Lang}}active selected{{end}}" href="{{if eq $.Lang .Lang}}#{{else}}{{$.Link}}?lang={{.Lang}}{{end}}">{{.Name}}</a> | |||||
| <!--<a lang="{{.Lang}}" class="item {{if eq $.Lang .Lang}}active selected{{end}}" href="{{if eq $.Lang .Lang}}#{{else}}{{$.Link}}?lang={{.Lang}}{{end}}">{{.Name}}</a>--> | |||||
| <a lang="{{.Lang}}" class="item {{if eq $.Lang .Lang}}active selected{{end}}" href="javascript:;" olang="{{$.Lang}}" lang="{{.Lang}}" >{{.Name}}</a> | |||||
| {{end}} | {{end}} | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <script> | |||||
| ;(function() { | |||||
| document.addEventListener('DOMContentLoaded', function() { | |||||
| $('.ui.language .menu .item').on('click', function() { | |||||
| var lang = $(this).attr('lang'); | |||||
| var oLang = $(this).attr('olang'); | |||||
| if (oLang === lang) return; | |||||
| var origin = window.location.origin; | |||||
| var pathname = window.location.pathname; | |||||
| var search = window.location.search; | |||||
| var hash = window.location.hash; | |||||
| var oHref = window.location.href; | |||||
| var urlSearchParams = new URLSearchParams(search); | |||||
| urlSearchParams.set('lang', lang); | |||||
| window.location.href = origin + pathname + '?' + urlSearchParams.toString() + hash; | |||||
| }); | |||||
| }); | |||||
| })(); | |||||
| </script> | |||||
| <a href="https://git.openi.org.cn/zeizei/OpenI_Learning" class="item" target="_blank"><i class="compass icon"></i> {{.i18n.Tr "custom.Platform_Tutorial"}} </a> | <a href="https://git.openi.org.cn/zeizei/OpenI_Learning" class="item" target="_blank"><i class="compass icon"></i> {{.i18n.Tr "custom.Platform_Tutorial"}} </a> | ||||
| {{if .EnableSwagger}}<a href="/api/swagger" class="item"><i class="plug icon" ></i> API</a>{{end}} | {{if .EnableSwagger}}<a href="/api/swagger" class="item"><i class="plug icon" ></i> API</a>{{end}} | ||||
| {{if .IsSigned}} | {{if .IsSigned}} | ||||
| @@ -262,8 +262,6 @@ | |||||
| <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | ||||
| <a class="active item" | <a class="active item" | ||||
| data-tab="first">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | data-tab="first">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | ||||
| <a class="item" data-tab="second" | |||||
| onclick="javascript:parseInfo()">{{$.i18n.Tr "repo.cloudbrain.runinfo"}}</a> | |||||
| <a class="item log_bottom" data-tab="third" | <a class="item log_bottom" data-tab="third" | ||||
| data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a> | data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a> | ||||
| <a class="item load-model-file" data-tab="four" | <a class="item load-model-file" data-tab="four" | ||||
| @@ -515,25 +513,6 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="ui tab" data-tab="second"> | |||||
| <div> | |||||
| <div class="ui message message{{.VersionName}}" style="display: none;"> | |||||
| <div id="header"></div> | |||||
| </div> | |||||
| <div class="ui attached" | |||||
| style="height: 390px !important; overflow: auto;"> | |||||
| <input type="hidden" id="json_value" value="{{$.result.JobStatus.AppExitDiagnostics}}"> | |||||
| <input type="hidden" id="ExitDiagnostics" value="{{$.ExitDiagnostics}}"> | |||||
| <span id="info_display" class="info_text"> | |||||
| </span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="ui tab" data-tab="third"> | <div class="ui tab" data-tab="third"> | ||||
| <div class="file-info"> | <div class="file-info"> | ||||
| <a id="{{.VersionName}}-log-down" | <a id="{{.VersionName}}-log-down" | ||||
| @@ -616,56 +595,6 @@ | |||||
| $(document).ready(function () { | $(document).ready(function () { | ||||
| $('.secondary.menu .item').tab(); | $('.secondary.menu .item').tab(); | ||||
| }); | }); | ||||
| let userName | |||||
| let repoPath | |||||
| let jobID | |||||
| let downlaodFlag = {{ $.canDownload }} | |||||
| let taskID = {{ $.task.ID }} | |||||
| let realJobName = {{ $.task.JobName }} | |||||
| function parseInfo() { | |||||
| let jsonValue = document.getElementById("json_value").value; | |||||
| let jsonObj = JSON.parse(jsonValue); | |||||
| let podRoleName = jsonObj["podRoleName"]; | |||||
| let html = ""; | |||||
| if (podRoleName != null) { | |||||
| let task0 = podRoleName["task1-0"]; | |||||
| let podEvents = jsonObj["podEvents"]; | |||||
| let podEventArray = podEvents[task0]; | |||||
| if (podEventArray != null) { | |||||
| for (var i = 0; i < podEventArray.length; i++) { | |||||
| if (podEventArray[i]["reason"] != "") { | |||||
| html += "<p><b>[" + podEventArray[i]["reason"] + "]</b></p>"; | |||||
| html += "<p>" + podEventArray[i]["message"] + "</p>"; | |||||
| html += "<p>" + podEventArray[i]["action"] + "</p>"; | |||||
| } | |||||
| } | |||||
| } | |||||
| let extras = jsonObj["extras"]; | |||||
| if (extras != null) { | |||||
| for (var i = 0; i < extras.length; i++) { | |||||
| if (extras[i]["reason"] != "") { | |||||
| html += "<p><b>[" + extras[i]["reason"] + "]</b></p>"; | |||||
| html += "<p>" + extras[i]["message"] + "</p>"; | |||||
| html += "<p>" + extras[i]["action"] + "</p>"; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| let string = document.getElementById("ExitDiagnostics").value; | |||||
| string = string.replace(/\r\n/g, "<br>") | |||||
| string = string.replace(/\n/g, "<br>"); | |||||
| string = string.replace(/(\r\n)|(\n)/g, '<br>'); | |||||
| if (string != "") { | |||||
| html += "<p><b>[ExitDiagnostics]</b></p>"; | |||||
| html += "<p>" + string + "</p>"; | |||||
| } | |||||
| document.getElementById("info_display").innerHTML = html; | |||||
| } | |||||
| ;(function() { | ;(function() { | ||||
| var SPEC = {{ .Spec }}; | var SPEC = {{ .Spec }}; | ||||
| var showPoint = false; | var showPoint = false; | ||||
| @@ -284,15 +284,10 @@ | |||||
| <div class="content-pad"> | <div class="content-pad"> | ||||
| <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | ||||
| <a class="active item" | <a class="active item" | ||||
| data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | |||||
| <a class="item" data-tab="second{{$k}}" | |||||
| onclick="javascript:parseInfo()">{{$.i18n.Tr "repo.cloudbrain.runinfo"}}</a> | |||||
| data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | |||||
| <a class="item log_bottom" data-tab="third{{$k}}" | <a class="item log_bottom" data-tab="third{{$k}}" | ||||
| data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a> | |||||
| data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a> | |||||
| <a class="item load-model-file" data-tab="four{{$k}}" data-gpu-flag="true" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}/model_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | <a class="item load-model-file" data-tab="four{{$k}}" data-gpu-flag="true" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}/model_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | ||||
| </div> | </div> | ||||
| <div class="ui tab active" data-tab="first{{$k}}"> | <div class="ui tab active" data-tab="first{{$k}}"> | ||||
| @@ -430,9 +425,6 @@ | |||||
| </div> | </div> | ||||
| </td> | </td> | ||||
| </tr> | </tr> | ||||
| <tr class="ti-no-ng-animate"> | <tr class="ti-no-ng-animate"> | ||||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | <td class="ti-no-ng-animate ti-text-form-label text-width80"> | ||||
| {{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} | {{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} | ||||
| @@ -504,25 +496,6 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="ui tab" data-tab="second{{$k}}"> | |||||
| <div> | |||||
| <div class="ui message message{{.VersionName}}" style="display: none;"> | |||||
| <div id="header"></div> | |||||
| </div> | |||||
| <div class="ui attached log" id="log_state{{.VersionName}}" | |||||
| style="height: 390px !important; overflow: auto;"> | |||||
| <input type="hidden" id="json_value" value="{{$.result.JobStatus.AppExitDiagnostics}}"> | |||||
| <input type="hidden" id="ExitDiagnostics" value="{{$.ExitDiagnostics}}"> | |||||
| <span id="info_display" class="info_text"> | |||||
| </span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="ui tab" data-tab="third{{$k}}"> | <div class="ui tab" data-tab="third{{$k}}"> | ||||
| <div class="file-info"> | <div class="file-info"> | ||||
| <a id="{{.VersionName}}-log-down" | <a id="{{.VersionName}}-log-down" | ||||
| @@ -565,29 +538,22 @@ | |||||
| <input type="hidden" name="init_log" value> | <input type="hidden" name="init_log" value> | ||||
| <pre id="log_file{{.VersionName}}"></pre> | <pre id="log_file{{.VersionName}}"></pre> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="ui tab" data-tab="four{{$k}}"> | <div class="ui tab" data-tab="four{{$k}}"> | ||||
| <input type="hidden" name="model{{.VersionName}}" value="-1"> | <input type="hidden" name="model{{.VersionName}}" value="-1"> | ||||
| <input type="hidden" name="modelback{{.VersionName}}" value="-1"> | <input type="hidden" name="modelback{{.VersionName}}" value="-1"> | ||||
| <div class='ui breadcrumb model_file_bread' id='file_breadcrumb{{.VersionName}}'> | <div class='ui breadcrumb model_file_bread' id='file_breadcrumb{{.VersionName}}'> | ||||
| <div class="active section">result</div> | <div class="active section">result</div> | ||||
| <div class="divider"> / </div> | <div class="divider"> / </div> | ||||
| </div> | </div> | ||||
| <div id="dir_list{{.VersionName}}"> | <div id="dir_list{{.VersionName}}"> | ||||
| </div> | </div> | ||||
| <div style="display:flex;align-items: center;justify-content: end;color: #f2711c;"> | <div style="display:flex;align-items: center;justify-content: end;color: #f2711c;"> | ||||
| <i class="ri-error-warning-line" style="margin-right:0.5rem;"></i> | <i class="ri-error-warning-line" style="margin-right:0.5rem;"></i> | ||||
| <span>{{$.i18n.Tr "repo.file_limit_100"}}</span> | <span>{{$.i18n.Tr "repo.file_limit_100"}}</span> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -700,11 +666,8 @@ | |||||
| <button class="ui button cancel">{{.i18n.Tr "repo.cloudbrain.cancel"}}</button> | <button class="ui button cancel">{{.i18n.Tr "repo.cloudbrain.cancel"}}</button> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{template "base/footer" .}} | {{template "base/footer" .}} | ||||
| <script type="text/javascript" src="/self/ztree/js/jquery.ztree.core.js"></script> | <script type="text/javascript" src="/self/ztree/js/jquery.ztree.core.js"></script> | ||||
| @@ -712,7 +675,15 @@ | |||||
| <script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script> | <script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script> | ||||
| <script> | <script> | ||||
| var setting = { | |||||
| var userName; | |||||
| var repoPath; | |||||
| $(document).ready(function(){ | |||||
| var url = window.location.href; | |||||
| var urlArr = url.split('/') | |||||
| userName = urlArr.slice(-5)[0] | |||||
| repoPath = urlArr.slice(-4)[0] | |||||
| }); | |||||
| var setting = { | |||||
| check: { | check: { | ||||
| enable: true, | enable: true, | ||||
| chkboxType: {"Y":"ps", "N":"ps"} | chkboxType: {"Y":"ps", "N":"ps"} | ||||
| @@ -922,110 +893,7 @@ | |||||
| $('.secondary.menu .item').tab(); | $('.secondary.menu .item').tab(); | ||||
| }); | }); | ||||
| let userName | |||||
| let repoPath | |||||
| let jobID | |||||
| let downlaodFlag = {{ $.canDownload }} | |||||
| let taskID = {{ $.task.ID }} | |||||
| let realJobName = {{ $.task.JobName }} | |||||
| $(document).ready(function () { | |||||
| let url = window.location.href; | |||||
| let urlArr = url.split('/') | |||||
| userName = urlArr.slice(-5)[0] | |||||
| repoPath = urlArr.slice(-4)[0] | |||||
| jobID = urlArr.slice(-1)[0] | |||||
| }) | |||||
| function stopBubbling(e) { | |||||
| e = window.event || e; | |||||
| if (e.stopPropagation) { | |||||
| e.stopPropagation(); //阻止事件 冒泡传播 | |||||
| } else { | |||||
| e.cancelBubble = true; //ie兼容 | |||||
| } | |||||
| } | |||||
| function loadLog(version_name) { | |||||
| document.getElementById("mask").style.display = "block" | |||||
| let startLine = $('input[name=end_line]').val(); | |||||
| if(startLine==""){ | |||||
| startLine=0; | |||||
| } | |||||
| let endLine = $('input[name=end_line]').val(); | |||||
| if(endLine==""){ | |||||
| endLine = 50; | |||||
| } | |||||
| $.get(`/${userName}/${repoPath}/cloudbrain/train-job/${jobID}/get_log?endLine=${endLine}&startLine=${startLine}`, (data) => { | |||||
| $('input[name=end_line]').val(data.EndLine) | |||||
| $('input[name=start_line]').val(data.StartLine) | |||||
| $(`#log_file${version_name}`).text(data.Content) | |||||
| document.getElementById("mask").style.display = "none" | |||||
| }).fail(function (err) { | |||||
| console.log(err); | |||||
| document.getElementById("mask").style.display = "none" | |||||
| }); | |||||
| } | |||||
| function refreshStatus(version_name) { | |||||
| $.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/${taskID}?version_name=${versionname}`, (data) => { | |||||
| // header status and duration | |||||
| //$(`#${version_name}-duration-span`).text(data.JobDuration) | |||||
| $(`#${version_name}-status-span span`).text(data.JobStatus) | |||||
| $(`#${version_name}-status-span i`).attr("class", data.JobStatus) | |||||
| // detail status and duration | |||||
| //$('#'+version_name+'-duration').text(data.JobDuration) | |||||
| $('#' + version_name + '-status').text(data.JobStatus) | |||||
| loadLog(version_name) | |||||
| }).fail(function (err) { | |||||
| console.log(err); | |||||
| }); | |||||
| stopBubbling(arguments.callee.caller.arguments[0]) | |||||
| } | |||||
| function parseInfo() { | |||||
| let jsonValue = document.getElementById("json_value").value; | |||||
| let jsonObj = JSON.parse(jsonValue); | |||||
| let podRoleName = jsonObj["podRoleName"]; | |||||
| let html = ""; | |||||
| if (podRoleName != null) { | |||||
| let task0 = podRoleName["task1-0"]; | |||||
| let podEvents = jsonObj["podEvents"]; | |||||
| let podEventArray = podEvents[task0]; | |||||
| if (podEventArray != null) { | |||||
| for (var i = 0; i < podEventArray.length; i++) { | |||||
| if (podEventArray[i]["reason"] != "") { | |||||
| html += "<p><b>[" + podEventArray[i]["reason"] + "]</b></p>"; | |||||
| html += "<p>" + podEventArray[i]["message"] + "</p>"; | |||||
| html += "<p>" + podEventArray[i]["action"] + "</p>"; | |||||
| } | |||||
| } | |||||
| } | |||||
| let extras = jsonObj["extras"]; | |||||
| if (extras != null) { | |||||
| for (var i = 0; i < extras.length; i++) { | |||||
| if (extras[i]["reason"] != "") { | |||||
| html += "<p><b>[" + extras[i]["reason"] + "]</b></p>"; | |||||
| html += "<p>" + extras[i]["message"] + "</p>"; | |||||
| html += "<p>" + extras[i]["action"] + "</p>"; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| let string = document.getElementById("ExitDiagnostics").value; | |||||
| string = string.replace(/\r\n/g, "<br>") | |||||
| string = string.replace(/\n/g, "<br>"); | |||||
| string = string.replace(/(\r\n)|(\n)/g, '<br>'); | |||||
| if (string != "") { | |||||
| html += "<p><b>[ExitDiagnostics]</b></p>"; | |||||
| html += "<p>" + string + "</p>"; | |||||
| } | |||||
| document.getElementById("info_display").innerHTML = html; | |||||
| } | |||||
| ;(function() { | ;(function() { | ||||
| var SPEC = {{ .Spec }}; | var SPEC = {{ .Spec }}; | ||||
| var showPoint = false; | var showPoint = false; | ||||
| @@ -238,11 +238,8 @@ | |||||
| <span> | <span> | ||||
| <div style="float: right;"> | <div style="float: right;"> | ||||
| {{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
| </div> | </div> | ||||
| <div class="ac-display-inblock title_text acc-margin-bottom"> | <div class="ac-display-inblock title_text acc-margin-bottom"> | ||||
| <span class="cti-mgRight-sm">{{TimeSinceUnix1 .CreatedUnix}}</span> | <span class="cti-mgRight-sm">{{TimeSinceUnix1 .CreatedUnix}}</span> | ||||
| <span class="cti-mgRight-sm"> | <span class="cti-mgRight-sm"> | ||||
| {{$.i18n.Tr "repo.modelarts.current_version"}}:{{.VersionName}}</span> | {{$.i18n.Tr "repo.modelarts.current_version"}}:{{.VersionName}}</span> | ||||
| @@ -260,7 +257,6 @@ | |||||
| <span class="refresh-status" data-tooltip="刷新" style="cursor: pointer;" data-inverted="" data-version="{{.VersionName}}"> | <span class="refresh-status" data-tooltip="刷新" style="cursor: pointer;" data-inverted="" data-version="{{.VersionName}}"> | ||||
| <i class="redo icon redo-color"></i> | <i class="redo icon redo-color"></i> | ||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| <div style="float: right;"> | <div style="float: right;"> | ||||
| {{if and ($.canDownload) (ne .Status "WAITING") ($.Permission.CanWrite $.UnitTypeModelManage) }} | {{if and ($.canDownload) (ne .Status "WAITING") ($.Permission.CanWrite $.UnitTypeModelManage) }} | ||||
| @@ -269,7 +265,6 @@ | |||||
| {{else}} | {{else}} | ||||
| <a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | <a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | ||||
| {{end}} | {{end}} | ||||
| </div> | </div> | ||||
| </span> | </span> | ||||
| </span> | </span> | ||||
| @@ -282,6 +277,9 @@ | |||||
| <a class="active item" data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | <a class="active item" data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | ||||
| <a class="item log_bottom" data-tab="second{{$k}}" data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a> | <a class="item log_bottom" data-tab="second{{$k}}" data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a> | ||||
| {{ if eq $.Spec.ComputeResource "NPU"}} | |||||
| <a class="item metric_chart" data-tab="four{{$k}}" data-version="{{.VersionName}}" data-path="{{$.RepoRelPath}}/grampus/train-job/{{.JobID}}/metrics">{{$.i18n.Tr "cloudbrain.resource_use"}}</a> | |||||
| {{end}} | |||||
| <a class="item load-model-file" data-tab="third{{$k}}" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/model_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | <a class="item load-model-file" data-tab="third{{$k}}" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/model_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | ||||
| </div> | </div> | ||||
| <div class="ui tab active" data-tab="first{{$k}}"> | <div class="ui tab active" data-tab="first{{$k}}"> | ||||
| @@ -564,6 +562,14 @@ | |||||
| </div> | </div> | ||||
| </div> | |||||
| <div class="ui tab" data-tab="four{{$k}}" style="position: relative;"> | |||||
| <i class="ri-refresh-line metric_chart" | |||||
| style="position: absolute;right: 25%;color:#3291f8;z-index:99;cursor: pointer;" | |||||
| data-version="{{.VersionName}}"></i> | |||||
| <div id="metric-{{.VersionName}}" style="height: 260px;width: 870px;"> | |||||
| </div> | |||||
| </div> | </div> | ||||
| <div class="ui tab" data-tab="third{{$k}}"> | <div class="ui tab" data-tab="third{{$k}}"> | ||||
| <input type="hidden" name="model{{.VersionName}}" value="-1"> | <input type="hidden" name="model{{.VersionName}}" value="-1"> | ||||
| @@ -321,7 +321,7 @@ | |||||
| data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | ||||
| <a class="item log_bottom" data-tab="second{{$k}}" | <a class="item log_bottom" data-tab="second{{$k}}" | ||||
| data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a> | data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a> | ||||
| <a class="item metric_chart" data-tab="four{{$k}}" data-version="{{.VersionName}}">{{$.i18n.Tr "cloudbrain.resource_use"}}</a> | |||||
| <a class="item metric_chart" data-tab="four{{$k}}" data-version="{{.VersionName}}" data-path="{{$.RepoRelPath}}/modelarts/train-job/{{.JobID}}/metric_statistics?version_name={{.VersionName}}&statistic_type=each&metrics=">{{$.i18n.Tr "cloudbrain.resource_use"}}</a> | |||||
| <a class="item load-model-file" data-tab="third{{$k}}" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/model_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | <a class="item load-model-file" data-tab="third{{$k}}" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/model_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | ||||
| </div> | </div> | ||||
| <div class="ui tab active" data-tab="first{{$k}}"> | <div class="ui tab active" data-tab="first{{$k}}"> | ||||
| @@ -726,13 +726,12 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{template "base/footer" .}} | {{template "base/footer" .}} | ||||
| <script type="text/javascript" src="/self/ztree/js/jquery.ztree.core.js"></script> | <script type="text/javascript" src="/self/ztree/js/jquery.ztree.core.js"></script> | ||||
| <script type="text/javascript" src="/self/ztree/js/jquery.ztree.excheck.js"></script> | <script type="text/javascript" src="/self/ztree/js/jquery.ztree.excheck.js"></script> | ||||
| <script> | |||||
| <script> | |||||
| var setting = { | var setting = { | ||||
| check: { | check: { | ||||
| enable: true, | enable: true, | ||||
| @@ -0,0 +1,10 @@ | |||||
| {{template "base/head" .}} | |||||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-modelmanage-local-create-1.css?v={{MD5 AppVer}}" /> | |||||
| <div class="repository release dataset-list view"> | |||||
| {{template "repo/header" .}} | |||||
| <div class="ui container"> | |||||
| <div id="__vue-root"></div> | |||||
| </div> | |||||
| </div> | |||||
| <script src="{{StaticUrlPrefix}}/js/vp-modelmanage-local-create-1.js?v={{MD5 AppVer}}"></script> | |||||
| {{template "base/footer" .}} | |||||
| @@ -0,0 +1,11 @@ | |||||
| {{template "base/head" .}} | |||||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-modelmanage-local-create-2.css?v={{MD5 AppVer}}" /> | |||||
| <div class="repository release dataset-list view"> | |||||
| {{template "repo/header" .}} | |||||
| <script>var MAX_MODEL_SIZE = {{ .max_model_size }};</script> | |||||
| <div class="ui container"> | |||||
| <div id="__vue-root"></div> | |||||
| </div> | |||||
| </div> | |||||
| <script src="{{StaticUrlPrefix}}/js/vp-modelmanage-local-create-2.js?v={{MD5 AppVer}}"></script> | |||||
| {{template "base/footer" .}} | |||||
| @@ -0,0 +1,581 @@ | |||||
| {{template "base/head" .}} | |||||
| <link rel="stylesheet" href="/self/ztree/css/zTreeStyle/zTreeStyle.css" type="text/css"> | |||||
| <style> | |||||
| #newmodel .header { | |||||
| height: 45px; | |||||
| border: 1px solid #d4d4d5; | |||||
| border-radius: 5px 5px 0 0; | |||||
| font-size: 14px; | |||||
| background: #f0f0f0; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| } | |||||
| #newmodel .content { | |||||
| margin-top: -1px; | |||||
| border: 1px solid #d4d4d5; | |||||
| border-top: none; | |||||
| } | |||||
| .inline.fields .right.aligned label{ | |||||
| width: 100% !important; | |||||
| text-align: right; | |||||
| } | |||||
| .inline .ui.dropdown .text { | |||||
| color: rgba(0, 0, 0, .87) !important; | |||||
| max-width: 360px; | |||||
| } | |||||
| .newtext{ | |||||
| margin-left: 12px !important | |||||
| } | |||||
| .menuContent{ | |||||
| position: absolute; | |||||
| background: #ffffff; | |||||
| left: 0; | |||||
| right: 26px; | |||||
| top: 36px; | |||||
| z-index:999; | |||||
| border: 1px solid #96c8da; | |||||
| border-top: 0; | |||||
| border-bottom-right-radius: 4px; | |||||
| border-bottom-left-radius: 4px; | |||||
| box-shadow: 0 2px 3px 0 rgb(34 36 38 / 15%); | |||||
| } | |||||
| </style> | |||||
| <div id="mask"> | |||||
| <div id="loadingPage"> | |||||
| <div class="rect1"></div> | |||||
| <div class="rect2"></div> | |||||
| <div class="rect3"></div> | |||||
| <div class="rect4"></div> | |||||
| <div class="rect5"></div> | |||||
| </div> | |||||
| </div> | |||||
| {{$repository := .Repository.ID}} | |||||
| <div class="repository release dataset-list view"> | |||||
| {{template "repo/header" .}} | |||||
| <div class="ui container"> | |||||
| <div id="newmodel"> | |||||
| <div class="ui second"> | |||||
| <div class="header" style="padding: 1rem;background-color: rgba(240, 240, 240, 100);"> | |||||
| <h4 id="model_header">{{.i18n.Tr "repo.model.manage.import_online_model"}}</h4> | |||||
| </div> | |||||
| <div class="content content-padding"> | |||||
| <form id="formId" class="ui form dirty"> | |||||
| <input class="ays-ignore" type="hidden" name="initModel" value="{{$.MODEL_COUNT}}"> | |||||
| <div class="ui error message"></div> | |||||
| <input class="ays-ignore" type="hidden" name="_csrf" value=""> | |||||
| <div class="inline fields"> | |||||
| <div class="required two wide field right aligned"> | |||||
| <label for="jobId">{{.i18n.Tr "repo.model.manage.select.trainjob"}}</label> | |||||
| </div> | |||||
| <div class="required thirteen wide inline field"> | |||||
| <div class="ui dropdown selection search loading" id="choice_model"> | |||||
| <input class="ays-ignore" type="hidden" id="jobId" name="jobId" required> | |||||
| <div class="default text">{{.i18n.Tr "repo.model.manage.select.trainjob"}}</div> | |||||
| <i class="dropdown icon"></i> | |||||
| <div class="menu" id="job-name"> | |||||
| </div> | |||||
| </div> | |||||
| <label for="versionName">{{.i18n.Tr "repo.model.manage.version"}}</label> | |||||
| <span> </span> | |||||
| <div class="ui dropdown selection search" id="choice_version"> | |||||
| <input class="ays-ignore" type="hidden" id="versionName" name="versionName" required> | |||||
| <div class="default text">{{.i18n.Tr "repo.model.manage.select.version"}}</div> | |||||
| <i class="dropdown icon"></i> | |||||
| <div class="menu" id="job-version"> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="required inline fields" id="modelname"> | |||||
| <div class="two wide field right aligned"> | |||||
| <label for="name">{{.i18n.Tr "repo.model.manage.model_name"}}</label> | |||||
| </div> | |||||
| <div class="eight wide field"> | |||||
| <input class="ays-ignore" id="name" name="name" required maxlength="25" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | |||||
| </div> | |||||
| </div> | |||||
| <div class="required inline fields" id="verionName" style="display:none;"> | |||||
| <div class="two wide field right aligned"> | |||||
| <label for="version">{{.i18n.Tr "repo.model.manage.version"}}</label> | |||||
| </div> | |||||
| <div class="eight wide field"> | |||||
| <input class="ays-ignore" id="version" name="version" value="" readonly required maxlength="255"> | |||||
| </div> | |||||
| </div> | |||||
| <div class="unite min_title inline fields required"> | |||||
| <div class="two wide field right aligned"> | |||||
| <label for="Engine">{{.i18n.Tr "repo.model.manage.engine"}}</label> | |||||
| </div> | |||||
| <div class="ui ten wide field dropdown selection" id="choice_Engine"> | |||||
| <input class="ays-ignore" type="hidden" id="engine" name="engine" required> | |||||
| <div class="default text newtext">{{.i18n.Tr "repo.model.manage.select.engine"}}</div> | |||||
| <i class="dropdown icon"></i> | |||||
| <div class="menu" id="job-Engine"> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="unite min_title inline fields required"> | |||||
| <div class="two wide field right aligned"> | |||||
| <label for="modelSelectedFile">{{.i18n.Tr "repo.model.manage.modelfile"}}</label> | |||||
| </div> | |||||
| <div class="thirteen wide field" style="position:relative"> | |||||
| <input class="ays-ignore" id="modelSelectedFile" type="text" readonly required onclick="showMenu();" name="modelSelectedFile" > | |||||
| <div id="menuContent" class="menuContent" style="display:none;"> | |||||
| <ul id="treeDemo" class="ztree"></ul> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="inline fields"> | |||||
| <div class="two wide field right aligned"> | |||||
| <label for="Label">{{.i18n.Tr "repo.model.manage.modellabel"}}  </label> | |||||
| </div> | |||||
| <div class="thirteen wide field"> | |||||
| <input class="ays-ignore" id="label" name="label" maxlength="255" placeholder='{{.i18n.Tr "repo.modelarts.train_job.label_place"}}'> | |||||
| </div> | |||||
| </div> | |||||
| <div class="inline fields"> | |||||
| <div class="two wide field right aligned"> | |||||
| <label for="description">{{.i18n.Tr "repo.model.manage.modeldesc"}}  </label> | |||||
| </div> | |||||
| <div class="thirteen wide field"> | |||||
| <textarea id="description" class="ays-ignore" name="description" rows="3" | |||||
| maxlength="255" placeholder='{{.i18n.Tr "repo.modelarts.train_job.new_place"}}' | |||||
| onchange="this.value=this.value.substring(0, 255)" | |||||
| onkeydown="this.value=this.value.substring(0, 255)" | |||||
| onkeyup="this.value=this.value.substring(0, 256)"></textarea> | |||||
| </div> | |||||
| </div> | |||||
| </form> | |||||
| <div class="inline field" style="margin-left:140px;margin-top:28px;"> | |||||
| <button id="submitId" type="button" class="ui create_train_job green button" onclick="submitSaveModel()" | |||||
| style=""> | |||||
| {{.i18n.Tr "repo.model.manage.sava_model"}} | |||||
| </button> | |||||
| <button style="margin-left:0px;" class="ui button cancel" onclick="backToModelListPage()">{{.i18n.Tr "repo.cloudbrain.cancel"}}</button> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| {{template "base/footer" .}} | |||||
| <script type="text/javascript" src="/self/ztree/js/jquery.ztree.core.js"></script> | |||||
| <script type="text/javascript" src="/self/ztree/js/jquery.ztree.excheck.js"></script> | |||||
| <script> | |||||
| ;(function() { | |||||
| var setting = { | |||||
| check: { | |||||
| enable: true, | |||||
| chkboxType: {"Y":"ps", "N":"ps"} | |||||
| }, | |||||
| view: { | |||||
| dblClickExpand: false | |||||
| }, | |||||
| callback: { | |||||
| beforeClick: beforeClick, | |||||
| onCheck: onCheck | |||||
| } | |||||
| }; | |||||
| function beforeClick(treeId, treeNode) { | |||||
| var zTree = $.fn.zTree.getZTreeObj("treeDemo"); | |||||
| zTree.checkNode(treeNode, !treeNode.checked, null, true); | |||||
| return false; | |||||
| } | |||||
| function onCheck(e, treeId, treeNode) { | |||||
| var zTree = $.fn.zTree.getZTreeObj("treeDemo"), | |||||
| nodes = zTree.getCheckedNodes(true), | |||||
| v = ""; | |||||
| for (var i=0, l=nodes.length; i<l; i++) { | |||||
| if(nodes[i].isParent){ | |||||
| continue; | |||||
| } | |||||
| var pathNodes = nodes[i].getPath(); | |||||
| var path =""; | |||||
| for(var j=0;j<pathNodes.length;j++){ | |||||
| if(j ==0){ | |||||
| path += pathNodes[j].name; | |||||
| }else{ | |||||
| path += "/" + pathNodes[j].name; | |||||
| } | |||||
| } | |||||
| v += path + ";"; | |||||
| } | |||||
| if (v.length > 0 ) v = v.substring(0, v.length-1); | |||||
| var cityObj = $("#modelSelectedFile"); | |||||
| cityObj.attr("value", v); | |||||
| } | |||||
| function showMenu() { | |||||
| var cityObj = $("#modelSelectedFile"); | |||||
| var cityOffset = $("#modelSelectedFile").offset(); | |||||
| // $("#menuContent").css({left:cityOffset.left + "px", top:cityOffset.top + cityObj.outerHeight() + "px"}).slideDown("fast"); | |||||
| $("#menuContent").slideDown("fast"); | |||||
| $("body").bind("mousedown", onBodyDown); | |||||
| } | |||||
| window.showMenu = showMenu; | |||||
| function hideMenu() { | |||||
| $("#menuContent").fadeOut("fast"); | |||||
| $("body").unbind("mousedown", onBodyDown); | |||||
| } | |||||
| function onBodyDown(event) { | |||||
| if (!(event.target.id == "menuBtn" || event.target.id == "modelSelectedFile" || event.target.id == "menuContent" || $(event.target).parents("#menuContent").length>0)) { | |||||
| hideMenu(); | |||||
| } | |||||
| } | |||||
| $(document).ready(function(){ | |||||
| //$.fn.zTree.init($("#treeDemo"), setting, zNodes); | |||||
| }); | |||||
| let repolink = {{.RepoLink }} | |||||
| let repoId = {{ $repository }} | |||||
| const { _AppSubUrl, _StaticUrlPrefix, csrf } = window.config; | |||||
| $('input[name="_csrf"]').val(csrf) | |||||
| let modelData; | |||||
| function createModelName() { | |||||
| let repoName = location.pathname.split('/')[2] | |||||
| let modelName = repoName + '_model_' + Math.random().toString(36).substr(2, 4) | |||||
| $('#name').val(modelName) | |||||
| $('#version').val("0.0.1") | |||||
| } | |||||
| let dirKey="isOnlyDir--:&"; | |||||
| /* | |||||
| function showcreate(obj) { | |||||
| $('.ui.modal.second') | |||||
| .modal({ | |||||
| centered: false, | |||||
| onShow: function () { | |||||
| $('input[name="version"]').addClass('model_disabled') | |||||
| $('.ui.dimmer').css({ "background-color": "rgb(136, 136, 136,0.7)" }) | |||||
| $("#job-name").empty() | |||||
| createModelName() | |||||
| loadTrainList() | |||||
| }, | |||||
| onHide: function () { | |||||
| var cityObj = $("#modelSelectedFile"); | |||||
| cityObj.attr("value", ""); | |||||
| document.getElementById("formId").reset(); | |||||
| $('#choice_model').dropdown('clear') | |||||
| $('#choice_version').dropdown('clear') | |||||
| $('#choice_Engine').dropdown('clear') | |||||
| $('.ui.dimmer').css({ "background-color": "" }) | |||||
| $('.ui.error.message').text() | |||||
| $('.ui.error.message').css('display', 'none') | |||||
| } | |||||
| }) | |||||
| .modal('show') | |||||
| } | |||||
| */ | |||||
| $('input[name="version"]').addClass('model_disabled') | |||||
| $('.ui.dimmer').css({ "background-color": "rgb(136, 136, 136,0.7)" }) | |||||
| $("#job-name").empty() | |||||
| createModelName() | |||||
| loadTrainList() | |||||
| $(function () { | |||||
| $('#choice_model').dropdown({ | |||||
| onChange: function (value) { | |||||
| $("#choice_version").addClass("loading") | |||||
| $('#choice_version').dropdown('clear') | |||||
| $("#job-version").empty() | |||||
| loadTrainVersion(value) | |||||
| } | |||||
| }) | |||||
| $('#choice_version').dropdown({ | |||||
| onChange: function (value) { | |||||
| console.log("model version:" + value); | |||||
| if (modelData != null) { | |||||
| for (var i = 0; i < modelData.length; i++) { | |||||
| if (modelData[i].VersionName == value) { | |||||
| setEngine(modelData[i]); | |||||
| loadModelFile(modelData[i]); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| }) | |||||
| }); | |||||
| function versionAdd(version) { | |||||
| let versionArray = version.split('.') | |||||
| if (versionArray[2] == '9') { | |||||
| if (versionArray[1] == '9') { | |||||
| versionArray[0] = String(Number(versionArray[1]) + 1) | |||||
| versionArray[1] = '0' | |||||
| } else { | |||||
| versionArray[1] = String(Number(versionArray[1]) + 1) | |||||
| } | |||||
| versionArray[2] = '0' | |||||
| } else { | |||||
| versionArray[2] = String(Number(versionArray[2]) + 1) | |||||
| } | |||||
| return versionArray.join('.') | |||||
| } | |||||
| function loadTrainList() { | |||||
| $.get(`${repolink}/modelmanage/query_train_job?repoId=${repoId}`, (data) => { | |||||
| const n_length = data.length | |||||
| if(n_length > 0){ | |||||
| let train_html = '' | |||||
| for (let i = 0; i < n_length; i++) { | |||||
| train_html += `<div class="item" data-value="${data[i].JobID}">${data[i].DisplayJobName}</div>` | |||||
| train_html += '</div>' | |||||
| } | |||||
| $("#job-name").append(train_html) | |||||
| $("#choice_model").removeClass("loading") | |||||
| $('#choice_model .default.text').text(data[0].DisplayJobName) | |||||
| $('#choice_model input[name="jobId"]').val(data[0].JobID) | |||||
| loadTrainVersion() | |||||
| }else{ | |||||
| $("#choice_model").removeClass("loading") | |||||
| } | |||||
| }) | |||||
| } | |||||
| function loadTrainVersion(value) { | |||||
| let tmp = $('#choice_model input[name="jobId"]').val(); | |||||
| let jobId = !value ? $('#choice_model input[name="jobId"]').val() : value | |||||
| $.get(`${repolink}/modelmanage/query_train_job_version?jobId=${jobId}`, (data) => { | |||||
| const n_length = data.length | |||||
| let train_html = ''; | |||||
| modelData = data; | |||||
| for (let i = 0; i < n_length; i++) { | |||||
| var VersionName = data[i].VersionName || 'V0001'; | |||||
| train_html += `<div class="item" data-value="${VersionName}">${VersionName}</div>` | |||||
| train_html += '</div>' | |||||
| } | |||||
| if (data.length) { | |||||
| $("#job-version").append(train_html) | |||||
| $("#choice_version").removeClass("loading") | |||||
| var versionName = data[0].VersionName; | |||||
| if (versionName == null || versionName == "") { | |||||
| versionName = "V0001"; | |||||
| } | |||||
| $('#choice_version .default.text').text(versionName) | |||||
| $('#choice_version input[name="versionName"]').val(versionName) | |||||
| setEngine(data[0]) | |||||
| loadModelFile(data[0]) | |||||
| } | |||||
| }) | |||||
| } | |||||
| function loadModelFile(trainJob){ | |||||
| console.log("trainJob=", trainJob); | |||||
| $('#choice_file').dropdown('clear') | |||||
| $("#model-file").empty() | |||||
| if(trainJob ==null || trainJob ==""){ | |||||
| console.log("trainJob is null"); | |||||
| }else{ | |||||
| let type = trainJob.Type; | |||||
| if(type == 2){ | |||||
| if(trainJob.ComputeResource=="NPU"){ | |||||
| type=1; | |||||
| }else{ | |||||
| type=0; | |||||
| } | |||||
| } | |||||
| $.get(`${repolink}/modelmanage/query_train_model?jobName=${trainJob.JobName}&type=${type}&versionName=${trainJob.VersionName}`, (data) => { | |||||
| var cityObj = $("#modelSelectedFile"); | |||||
| cityObj.attr("value", ""); | |||||
| const n_length = data.length | |||||
| let file_html='' | |||||
| let firstFileName ='' | |||||
| var zNodes=[]; | |||||
| var nodesMap={}; | |||||
| for (let i=0;i<n_length;i++){ | |||||
| var parentNodeMap = nodesMap; | |||||
| var fileSplits = data[i].FileName.split("/"); | |||||
| for(let j=0;j < fileSplits.length;j++){ | |||||
| if(fileSplits[j] == ""){ | |||||
| break; | |||||
| } | |||||
| if(parentNodeMap[fileSplits[j]] == null){ | |||||
| parentNodeMap[fileSplits[j]] = {}; | |||||
| } | |||||
| parentNodeMap = parentNodeMap[fileSplits[j]]; | |||||
| } | |||||
| } | |||||
| for (let i=0;i<n_length;i++){ | |||||
| var parentNodeMap = nodesMap; | |||||
| var fileSplits = data[i].FileName.split("/"); | |||||
| for(let j=0;j < fileSplits.length;j++){ | |||||
| if(fileSplits[j] == ""){ | |||||
| if(data[i].FileName[data[i].FileName.length -1] =="/"){ | |||||
| if(Object.keys(parentNodeMap).length ==0){ | |||||
| parentNodeMap[dirKey]="true"; | |||||
| } | |||||
| } | |||||
| break; | |||||
| } | |||||
| parentNodeMap = parentNodeMap[fileSplits[j]]; | |||||
| } | |||||
| } | |||||
| convertToNode(zNodes,nodesMap); | |||||
| $.fn.zTree.init($("#treeDemo"), setting, zNodes); | |||||
| }) | |||||
| } | |||||
| } | |||||
| function convertToNode(nodeList,nodesMap){ | |||||
| var keyList = Object.keys(nodesMap); | |||||
| keyList.sort(function(a,b){ | |||||
| return a-b; | |||||
| }); | |||||
| var isFirst = true; | |||||
| for(var i=0; i<keyList.length;i++){ | |||||
| var node = {}; | |||||
| node["name"] = keyList[i]; | |||||
| nodeList.push(node); | |||||
| if(nodesMap[keyList[i]] != null && Object.keys(nodesMap[keyList[i]]).length >0){ | |||||
| if(nodesMap[keyList[i]][dirKey] != null){ | |||||
| node["open"] = false; | |||||
| node["isParent"] = true; | |||||
| }else{ | |||||
| node["children"]=[]; | |||||
| if(isFirst){ | |||||
| node["open"] = true; | |||||
| isFirst= false; | |||||
| } | |||||
| convertToNode(node["children"],nodesMap[keyList[i]]); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| function setEngine(trainJob) { | |||||
| console.log("trainJob=", trainJob); | |||||
| $('#choice_Engine').dropdown('clear') | |||||
| $("#job-Engine").empty() | |||||
| if (trainJob.EngineName != null && trainJob.EngineName != "") { | |||||
| srcEngine = trainJob.EngineName.split('-')[0] | |||||
| srcEngine = srcEngine.trim().toLowerCase(); | |||||
| let selectedText = "PyTorch"; | |||||
| let selectedValue = 0; | |||||
| let itemHtml = "<option class=\"item\" data-value=\"0\">PyTorch</option>"; | |||||
| if (srcEngine == 'tensorflow') { | |||||
| selectedText = "TensorFlow"; | |||||
| selectedValue = 1; | |||||
| itemHtml += "<option class=\"active item\" data-value=\"1\">TensorFlow</option>"; | |||||
| } else { | |||||
| itemHtml += "<option class=\"item\" data-value=\"1\">TensorFlow</option>"; | |||||
| } | |||||
| if (srcEngine == 'mindspore') { | |||||
| selectedText = "MindSpore"; | |||||
| selectedValue = 2; | |||||
| itemHtml += "<option class=\"active item\" data-value=\"2\">MindSpore</option>"; | |||||
| } else { | |||||
| itemHtml += "<option class=\"item\" data-value=\"2\">MindSpore</option>"; | |||||
| } | |||||
| itemHtml += "<option class=\"item\" data-value=\"4\">PaddlePaddle</option>" | |||||
| itemHtml += "<option class=\"item\" data-value=\"5\">OneFlow</option>" | |||||
| itemHtml += "<option class=\"item\" data-value=\"6\">MXNet</option>" | |||||
| itemHtml += "<option class=\"item\" data-value=\"3\">Other</option>" | |||||
| $('#choice_Engine .default.text').text(selectedText) | |||||
| $('#choice_Engine input[name="engine"]').val(selectedValue) | |||||
| $("#job-Engine").append(itemHtml); | |||||
| $("#choice_Engine").removeClass('disabled'); | |||||
| } else { | |||||
| let itemHtml = "<option class=\"active item\" data-value=\"0\">PyTorch</option>"; | |||||
| itemHtml += "<option class=\"item\" data-value=\"1\">TensorFlow</option>" | |||||
| itemHtml += "<option class=\"item\" data-value=\"2\">MindSpore</option>" | |||||
| itemHtml += "<option class=\"item\" data-value=\"4\">PaddlePaddle</option>" | |||||
| itemHtml += "<option class=\"item\" data-value=\"5\">OneFlow</option>" | |||||
| itemHtml += "<option class=\"item\" data-value=\"6\">MXNet</option>" | |||||
| itemHtml += "<option class=\"item\" data-value=\"3\">Other</option>" | |||||
| $('#choice_Engine .default.text').text("PyTorch"); | |||||
| $('#choice_Engine input[name="engine"]').val(0) | |||||
| $("#job-Engine").append(itemHtml); | |||||
| $("#choice_Engine").removeClass('disabled'); | |||||
| } | |||||
| } | |||||
| function check() { | |||||
| let jobid = document.getElementById("jobId").value; | |||||
| let versionname = document.getElementById("versionName").value; | |||||
| let name = document.getElementById("name").value; | |||||
| let version = document.getElementById("version").value; | |||||
| let modelSelectedFile = document.getElementById("modelSelectedFile").value; | |||||
| if (name == "") { | |||||
| $("#modelname").closest('.required').addClass("error"); | |||||
| return false; | |||||
| } else { | |||||
| $("#modelname").closest('.required').removeClass("error"); | |||||
| } | |||||
| if (versionname == "") { | |||||
| $("#verionname").closest('.required').addClass("error"); | |||||
| return false; | |||||
| } else { | |||||
| $("#verionname").closest('.required').removeClass("error"); | |||||
| } | |||||
| if (jobid == "") { | |||||
| $("#jobId").closest('.required').addClass("error"); | |||||
| return false; | |||||
| } else { | |||||
| $("#jobId").closest('.required').removeClass("error"); | |||||
| } | |||||
| if (modelSelectedFile == "") { | |||||
| $("#modelSelectedFile").closest('.required').addClass("error"); | |||||
| return false; | |||||
| } else { | |||||
| $("#modelSelectedFile").closest('.required').removeClass("error"); | |||||
| } | |||||
| if (versionname == "") { | |||||
| $("#versionName").closest('.required').addClass("error"); | |||||
| return false; | |||||
| } else { | |||||
| $("#versionName").closest('.required').removeClass("error"); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| function submitSaveModel() { | |||||
| let flag = check(); | |||||
| if (!flag) return false; | |||||
| $(".ui.error.message").hide(); | |||||
| let cName = $("input[name='name']").val(); | |||||
| let version = $("input[name='version']").val(); | |||||
| let data = $("#formId").serialize(); | |||||
| const initModel = $("input[name='initModel']").val(); | |||||
| let url_href = location.href.split("create_online_model")[0] + 'create_new_model'; | |||||
| $("#mask").css({ display: "block", "z-index": "9999" }); | |||||
| $.ajax({ | |||||
| url: url_href, | |||||
| type: "POST", | |||||
| data: data, | |||||
| success: function (res) { | |||||
| backToModelListPage(); | |||||
| }, | |||||
| error: function (xhr) { | |||||
| // 隐藏 loading | |||||
| // 只有请求不正常(状态码不为200)才会执行 | |||||
| $(".ui.error.message").text(xhr.responseText); | |||||
| $(".ui.error.message").show(); | |||||
| }, | |||||
| complete: function (xhr) { | |||||
| $("#mask").css({ display: "none", "z-index": "1" }); | |||||
| }, | |||||
| }); | |||||
| } | |||||
| function backToModelListPage() { | |||||
| let url_href = location.href.split("create_online_model")[0] + 'show_model'; | |||||
| window.location.href = url_href; | |||||
| } | |||||
| window.submitSaveModel = submitSaveModel; | |||||
| window.backToModelListPage = backToModelListPage; | |||||
| })(); | |||||
| </script> | |||||
| @@ -25,6 +25,23 @@ | |||||
| border-bottom-left-radius: 4px; | border-bottom-left-radius: 4px; | ||||
| box-shadow: 0 2px 3px 0 rgb(34 36 38 / 15%); | box-shadow: 0 2px 3px 0 rgb(34 36 38 / 15%); | ||||
| } | } | ||||
| .m-blue-btn { | |||||
| background-color: rgb(22, 132, 252) !important; | |||||
| } | |||||
| .m-blue-btn:hover { | |||||
| background-color: #66b1ff !important; | |||||
| color: #fff; | |||||
| } | |||||
| .m-blue-btn:focus { | |||||
| background-color: #66b1ff !important; | |||||
| color: #fff; | |||||
| } | |||||
| .m-blue-btn:active { | |||||
| background-color: #3a8ee6 !important; | |||||
| color: #fff; | |||||
| } | |||||
| </style> | </style> | ||||
| <link rel="stylesheet" href="/self/ztree/css/zTreeStyle/zTreeStyle.css" type="text/css"> | <link rel="stylesheet" href="/self/ztree/css/zTreeStyle/zTreeStyle.css" type="text/css"> | ||||
| @@ -57,8 +74,10 @@ | |||||
| </div> | </div> | ||||
| <div class="column right aligned"> | <div class="column right aligned"> | ||||
| <!-- --> | <!-- --> | ||||
| <a class="ui button {{if .Permission.CanWrite $.UnitTypeModelManage}} blue m-blue-btn {{else}} disabled {{end}}" | |||||
| href="{{.RepoLink}}/modelmanage/create_local_model_1">{{$.i18n.Tr "repo.model.manage.import_local_model"}}</a> | |||||
| <a class="ui button {{if .Permission.CanWrite $.UnitTypeModelManage}} green {{else}} disabled {{end}}" | <a class="ui button {{if .Permission.CanWrite $.UnitTypeModelManage}} green {{else}} disabled {{end}}" | ||||
| onclick="showcreate(this)">{{$.i18n.Tr "repo.model.manage.import_new_model"}}</a> | |||||
| href="{{.RepoLink}}/modelmanage/create_online_model">{{$.i18n.Tr "repo.model.manage.import_online_model"}}</a> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{if eq $.MODEL_COUNT 0}} | {{if eq $.MODEL_COUNT 0}} | ||||
| @@ -66,6 +85,7 @@ | |||||
| <div class="ui icon header bgtask-header-pic"></div> | <div class="ui icon header bgtask-header-pic"></div> | ||||
| <div class="bgtask-content-header">{{$.i18n.Tr "repo.model.manage.notcreatemodel"}}</div> | <div class="bgtask-content-header">{{$.i18n.Tr "repo.model.manage.notcreatemodel"}}</div> | ||||
| <div class="bgtask-content"> | <div class="bgtask-content"> | ||||
| <!-- | |||||
| {{if $.RepoIsEmpty}} | {{if $.RepoIsEmpty}} | ||||
| <div class="bgtask-content-txt">{{$.i18n.Tr "repo.model.manage.init1"}}<a href="{{.RepoLink}}">{{$.i18n.Tr "repo.model.manage.init2"}}</a></div> | <div class="bgtask-content-txt">{{$.i18n.Tr "repo.model.manage.init1"}}<a href="{{.RepoLink}}">{{$.i18n.Tr "repo.model.manage.init2"}}</a></div> | ||||
| {{end}} | {{end}} | ||||
| @@ -73,6 +93,8 @@ | |||||
| <div class="bgtask-content-txt">{{$.i18n.Tr "repo.model.manage.createtrainjob_tip"}}<a | <div class="bgtask-content-txt">{{$.i18n.Tr "repo.model.manage.createtrainjob_tip"}}<a | ||||
| href="{{.RepoLink}}/modelarts/train-job"> {{$.i18n.Tr "repo.model.manage.createtrainjob"}}</a></div> | href="{{.RepoLink}}/modelarts/train-job"> {{$.i18n.Tr "repo.model.manage.createtrainjob"}}</a></div> | ||||
| {{end}} | {{end}} | ||||
| --> | |||||
| <div class="bgtask-content-txt">{{$.i18n.Tr "repo.model.manage.createmodel_tip"}}<a href="{{.RepoLink}}/modelarts/train-job"> {{$.i18n.Tr "repo.model.manage.createtrainjob"}}</a></div> | |||||
| <div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions1"}}<a href="https://git.openi.org.cn/zeizei/OpenI_Learning"> {{$.i18n.Tr "repo.platform_instructions2"}} </a>{{$.i18n.Tr "repo.platform_instructions3"}}</div> | <div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions1"}}<a href="https://git.openi.org.cn/zeizei/OpenI_Learning"> {{$.i18n.Tr "repo.platform_instructions2"}} </a>{{$.i18n.Tr "repo.platform_instructions3"}}</div> | ||||
| </div> | </div> | ||||
| @@ -421,7 +443,8 @@ | |||||
| let train_html = ''; | let train_html = ''; | ||||
| modelData = data; | modelData = data; | ||||
| for (let i = 0; i < n_length; i++) { | for (let i = 0; i < n_length; i++) { | ||||
| train_html += `<div class="item" data-value="${data[i].VersionName}">${data[i].VersionName}</div>` | |||||
| var VersionName = data[i].VersionName || 'V0001'; | |||||
| train_html += `<div class="item" data-value="${VersionName}">${VersionName}</div>` | |||||
| train_html += '</div>' | train_html += '</div>' | ||||
| } | } | ||||
| if (data.length) { | if (data.length) { | ||||
| @@ -568,5 +591,4 @@ | |||||
| $("#choice_Engine").removeClass('disabled'); | $("#choice_Engine").removeClass('disabled'); | ||||
| } | } | ||||
| } | } | ||||
| </script> | </script> | ||||
| @@ -1,533 +1,10 @@ | |||||
| {{template "base/head" .}} | {{template "base/head" .}} | ||||
| <div class="repository"> | |||||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-modelmanage-common-detail.css?v={{MD5 AppVer}}" /> | |||||
| <div class="repository release dataset-list view"> | |||||
| {{template "repo/header" .}} | {{template "repo/header" .}} | ||||
| <style> | |||||
| .model_header_text{ | |||||
| font-size: 14px; | |||||
| color: #101010; | |||||
| font-weight: bold; | |||||
| } | |||||
| .ti_form{ | |||||
| text-align: left; | |||||
| max-width: 100%; | |||||
| vertical-align: middle; | |||||
| } | |||||
| .ti-text-form-label { | |||||
| padding-bottom: 20px; | |||||
| padding-right: 20px; | |||||
| color: #8a8e99; | |||||
| font-size: 14px; | |||||
| white-space: nowrap !important; | |||||
| width: 80px; | |||||
| line-height: 30px; | |||||
| } | |||||
| .ti-text-form-content { | |||||
| line-height: 30px; | |||||
| padding-bottom: 20px; | |||||
| width: 100%; | |||||
| } | |||||
| .change-version{ | |||||
| min-width: auto !important; | |||||
| border: 1px solid rgba(187, 187, 187, 100) !important; | |||||
| border-radius: .38571429rem !important; | |||||
| margin-left: 1.5em; | |||||
| } | |||||
| .title-word-elipsis{ | |||||
| overflow: hidden; | |||||
| text-overflow: ellipsis; | |||||
| white-space: nowrap; | |||||
| width: 30%; | |||||
| } | |||||
| .word-elipsis{ | |||||
| overflow: hidden; | |||||
| text-overflow: ellipsis; | |||||
| white-space: nowrap; | |||||
| padding-right: 80px; | |||||
| } | |||||
| .half-table{ | |||||
| width: 50%; | |||||
| float: left; | |||||
| } | |||||
| .text-width80 { | |||||
| width: 100px; | |||||
| line-height: 30px; | |||||
| } | |||||
| .tableStyle{ | |||||
| width:100%; | |||||
| table-layout: fixed; | |||||
| } | |||||
| .iword-elipsis{ | |||||
| display: inline-block; | |||||
| width: 80%; | |||||
| overflow: hidden; | |||||
| text-overflow: ellipsis; | |||||
| white-space: nowrap; | |||||
| } | |||||
| </style> | |||||
| <div class="ui container"> | <div class="ui container"> | ||||
| <h4 class="ui header" id="vertical-segment"> | |||||
| <!-- <a href="javascript:window.history.back();"><i class="arrow left icon"></i>返回</a> --> | |||||
| <div class="ui breadcrumb"> | |||||
| <a class="section" href="{{$.RepoLink}}/modelmanage/show_model"> | |||||
| {{$.i18n.Tr "repo.model.manage.model_manage"}} | |||||
| </a> | |||||
| <div class="divider"> / </div> | |||||
| <div class="active section">{{.name}}</div> | |||||
| </div> | |||||
| <select class="ui dropdown tiny change-version" id="dropdown" onchange="changeInfo(this.value)"> | |||||
| </select> | |||||
| </h4> | |||||
| <div id="showInfo" style="border:1px solid #e2e2e2;padding: 20px 60px;margin-top:24px"> | |||||
| <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | |||||
| <a class="active item" data-tab="first">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | |||||
| <a class="item" data-tab="second">{{$.i18n.Tr "repo.model_download"}}</a> | |||||
| </div> | |||||
| <div class="ui tab active" data-tab="first"> | |||||
| <div class="half-table"> | |||||
| <span class="model_header_text">{{$.i18n.Tr "repo.model.manage.baseinfo"}}</span> | |||||
| <table class="tableStyle" style="margin-top:20px;"> | |||||
| <tbody> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.model_name"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="modelName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.version"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="version" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.migrate_items_labels"}}</td> | |||||
| <td class="ti-text-form-content"> | |||||
| <div id="label" style="overflow: hidden;width: 95%;"> | |||||
| </div> | |||||
| </td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.model_size"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="size" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.createtime"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="createTime" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.description"}}</td> | |||||
| <td class="ti-text-form-content" > | |||||
| <div id="edit-td" style="display:flex"> | |||||
| <span id="description" title="" class="iword-elipsis"></span> | |||||
| <i id="edit-pencil" data-id="" data-desc="" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></i> | |||||
| </div> | |||||
| </td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"> | |||||
| <a id="displayJobNameHref" class="title" style="font-size: 14px;" target="_blank"> | |||||
| <span id="displayJobName" class="fitted" style="width: 90%;vertical-align: middle;"></span> | |||||
| </a> | |||||
| </td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.code_version"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="codeBranch" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.start_file"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="bootFile" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.train_dataset"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="datasetName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="parameters" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.AI_Engine"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="engineName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.standard"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="flavorName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.compute_node"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="workServerNumber" title=""></span></td> | |||||
| </tr> | |||||
| </tbody> | |||||
| </table> | |||||
| </div> | |||||
| <div class="half-table"> | |||||
| <span class="model_header_text">{{$.i18n.Tr "repo.model.manage.model_accuracy"}}</span> | |||||
| <table class="tableStyle" style="margin-top:20px;"> | |||||
| <tbody> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Accuracy"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Accuracy" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">F1</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="F1" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Precision"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Precision" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Recall"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Recall" title=""></span></td> | |||||
| </tr> | |||||
| </tbody> | |||||
| </table> | |||||
| </div> | |||||
| <div style="clear: both;"></div> | |||||
| </div> | |||||
| <div class="ui tab" data-tab="second"> | |||||
| <input type="hidden" name="model" value="-1"> | |||||
| <input type="hidden" name="modelback" value="-1"> | |||||
| <div class='ui breadcrumb model_file_bread' id='file_breadcrumb'> | |||||
| <div class="active section"></div> | |||||
| <div class="divider"> / </div> | |||||
| </div> | |||||
| <div id="dir_list"> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div id="__vue-root"></div> | |||||
| </div> | |||||
| </div> | </div> | ||||
| <script src="{{StaticUrlPrefix}}/js/vp-modelmanage-common-detail.js?v={{MD5 AppVer}}"></script> | |||||
| {{template "base/footer" .}} | {{template "base/footer" .}} | ||||
| <script> | |||||
| let url = location.href.split('show_model')[0] | |||||
| let trainJobUrl =url.split('modelmanage')[0] | |||||
| let ID = location.search.split('?name=').pop() | |||||
| $(document).ready(function(){ | |||||
| $('.secondary.menu .item').tab(); | |||||
| }); | |||||
| $(document).ready(loadInfo); | |||||
| function changeInfo(version){ | |||||
| $.get(`${url}show_model_info_api?name=${ID}`,(data)=>{ | |||||
| let versionData = data.filter((item)=>{ | |||||
| return item.version === version | |||||
| }) | |||||
| let returnArray = [] | |||||
| returnArray = transObj(versionData) | |||||
| let [initObj,initModelAcc,id] = returnArray | |||||
| editorCancel('','') | |||||
| renderInfo(initObj,initModelAcc,id) | |||||
| loadModelFile(versionData[0].id,versionData[0].version,'','','init') | |||||
| }) | |||||
| } | |||||
| function loadInfo(){ | |||||
| $.get(`${url}show_model_info_api?name=${ID}`,(data)=>{ | |||||
| let html = '' | |||||
| for (let i=0;i<data.length;i++){ | |||||
| if(!data[i].isCanOper){ | |||||
| $("#edit-pencil").css("display","none") | |||||
| } | |||||
| html += `<option value="${data[i].version}">${data[i].version}</option>` | |||||
| } | |||||
| $('#dropdown').append(html) | |||||
| let returnArray = [] | |||||
| returnArray = transObj(data) | |||||
| let [initObj,initModelAcc,id] = returnArray | |||||
| renderInfo(initObj,initModelAcc,id) | |||||
| loadModelFile(data[0].id,data[0].version,'','','init') | |||||
| }) | |||||
| } | |||||
| function getEngineName(model){ | |||||
| if(model.engine == 0){ | |||||
| return "PyTorch"; | |||||
| }else if(model.engine == 1 || model.engine == 121 || model.engine == 38){ | |||||
| return "TensorFlow"; | |||||
| }else if(model.engine == 2 || model.engine == 122 || model.engine == 35 || model.engine == 37){ | |||||
| return "MindSpore"; | |||||
| }else if(model.engine == 3){ | |||||
| return "Other"; | |||||
| }else if(model.engine == 4){ | |||||
| return "PaddlePaddle"; | |||||
| }else if(model.engine == 5){ | |||||
| return "OneFlow"; | |||||
| }else if(model.engine == 6){ | |||||
| return "MXNet"; | |||||
| } | |||||
| else{ | |||||
| return "Other" | |||||
| } | |||||
| } | |||||
| function transObj(data){ | |||||
| let {id,name,version,label,size,description,createdUnix,accuracy,codeBranch,codeCommitID,trainTaskInfo} = data[0] | |||||
| let modelAcc = JSON.parse(accuracy) | |||||
| trainTaskInfo = JSON.parse(trainTaskInfo) | |||||
| let engineName = getEngineName(data[0]) | |||||
| parameters = JSON.parse(trainTaskInfo.Parameters) | |||||
| parameters = parameters.parameter.length === 0 ? '--':parameters.parameter | |||||
| size = tranSize(size) | |||||
| let time = transTime(createdUnix) | |||||
| let initObj = { | |||||
| modelName:name || '--', | |||||
| version:version, | |||||
| label:label || '--', | |||||
| size:size, | |||||
| createTime:time, | |||||
| description:description || '--', | |||||
| codeBranch:codeBranch || '--', | |||||
| codeCommitID:codeCommitID || '--', | |||||
| bootFile:trainTaskInfo.BootFile || '--', | |||||
| datasetName:trainTaskInfo.DatasetName || '--', | |||||
| parameters:trainTaskInfo.Parameters || '--', | |||||
| flavorName:trainTaskInfo.FlavorName || '--', | |||||
| workServerNumber:trainTaskInfo.WorkServerNumber || '--', | |||||
| parameters:parameters, | |||||
| engineName:engineName, | |||||
| displayJobName:trainTaskInfo.DisplayJobName || '--', | |||||
| trainJobVersionName:trainTaskInfo.VersionName || '', | |||||
| cloudBrainJobID:trainTaskInfo.JobID|| '', | |||||
| cloudBrainType:trainTaskInfo.Type, | |||||
| } | |||||
| let initModelAcc = { | |||||
| Accuracy: modelAcc.Accuracy || '--', | |||||
| F1: modelAcc.F1 || '--', | |||||
| Precision:modelAcc.Precision || '--', | |||||
| Recall: modelAcc.Recall || '--' | |||||
| } | |||||
| return [initObj,initModelAcc,id] | |||||
| } | |||||
| function transTime(time){ | |||||
| let date = new Date(time * 1000);//时间戳为10位需*1000,时间戳为13位的话不需乘1000 | |||||
| let Y = date.getFullYear() + '-'; | |||||
| let M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1):date.getMonth()+1) + '-'; | |||||
| let D = (date.getDate()< 10 ? '0'+date.getDate():date.getDate())+ ' '; | |||||
| let h = (date.getHours() < 10 ? '0'+date.getHours():date.getHours())+ ':'; | |||||
| let m = (date.getMinutes() < 10 ? '0'+date.getMinutes():date.getMinutes()) + ':'; | |||||
| let s = date.getSeconds() < 10 ? '0'+date.getSeconds():date.getSeconds(); | |||||
| return Y+M+D+h+m+s; | |||||
| } | |||||
| function tranSize(value){ | |||||
| if(null==value||value==''){ | |||||
| return "0 Bytes"; | |||||
| } | |||||
| var unitArr = new Array("Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"); | |||||
| var index=0; | |||||
| var srcsize = parseFloat(value); | |||||
| index=Math.floor(Math.log(srcsize)/Math.log(1024)); | |||||
| var size =srcsize/Math.pow(1024,index); | |||||
| size=size.toFixed(2);//保留的小数位数 | |||||
| return size+unitArr[index]; | |||||
| } | |||||
| function editorFn(context){ | |||||
| let id= context.dataset.id | |||||
| let text = context.dataset.desc | |||||
| let textValue = text.replace(/enter;/g,'\r\n') | |||||
| $('#edit-td').replaceWith(`<div id='edit-div' style='width:80%;display: inline-block;'><textarea id='textarea-value' value='' rows='3' maxlength='255' style='width:80%;white-space: nowrap;' id='edit-text'>${textValue}</textarea><i class='check icon' style='color: #50d4ab;' onclick='editorSure("${text}","${id}")'></i><i class='times icon' style='color: #f66f6a;' onclick='editorCancel("${text}","${id}")'></i></div>`); | |||||
| } | |||||
| function editorCancel(text,id){ | |||||
| let objkey = text.replace(/enter;/g,'\r\n') | |||||
| $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${objkey}" class="iword-elipsis">${objkey}</span><i id="edit-pencil" data-id="${id}" data-desc="${text}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||||
| } | |||||
| function editorSure(text,id){ | |||||
| let description=$('#textarea-value').val() | |||||
| let sourcetext = $('#textarea-value').val().replace(/\n/g,'enter;') | |||||
| let data = { | |||||
| id:id, | |||||
| description:description | |||||
| } | |||||
| $.ajax({ | |||||
| url:`${url}modify_model`, | |||||
| type:'PUT', | |||||
| data:data | |||||
| }).done((res)=>{ | |||||
| $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${description}" class="iword-elipsis">${description}</span><i id="edit-pencil" data-id="${id}" data-desc="${sourcetext}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||||
| }) | |||||
| } | |||||
| function renderInfo(obj,accObj,id){ | |||||
| for(let key in obj){ | |||||
| if(key==="description"){ | |||||
| let descriptionText=obj[key].replace(/\r\n|\n/g,'enter;') | |||||
| $(`#${key}`).text(obj[key]) | |||||
| $(`#${key}`).attr("title",obj[key]) | |||||
| $('#edit-pencil').attr("data-id",id) | |||||
| $('#edit-pencil').attr("data-desc",descriptionText) | |||||
| } | |||||
| else if(key==="label"){ | |||||
| $('#Label').empty() | |||||
| if(obj[key]==='--'){ | |||||
| $('#Label').text(obj[key]) | |||||
| }else{ | |||||
| let labelArray = obj[key].trim().replace(/ +/g,' ').split(' ') | |||||
| let html='' | |||||
| for(let i=0;i<labelArray.length;i++){ | |||||
| html += `<a class="ui label" title="${labelArray[i]}">${labelArray[i]}</a>` | |||||
| } | |||||
| $('#Label').append(html) | |||||
| } | |||||
| } | |||||
| else if(key==="codeCommitID"){ | |||||
| let codeCommit = obj[key].slice(0,10) | |||||
| let html = `<a style="margin-left:1rem" class="ui label" title="${codeCommit}">${codeCommit}</a>` | |||||
| $('#CodeBranch').append(html) | |||||
| } | |||||
| else if(key==="displayJobName"){ | |||||
| let type=obj["cloudBrainType"] | |||||
| let href="" | |||||
| if(type==1){ | |||||
| href=trainJobUrl + "modelarts/train-job/" + obj["cloudBrainJobID"] | |||||
| }else if(type==0){ | |||||
| href=trainJobUrl + "cloudbrain/train-job/" + obj["cloudBrainJobID"] | |||||
| }else if(type==2){ | |||||
| href=trainJobUrl + "grampus/train-job/" + obj["CloudBrainJobID"] | |||||
| } | |||||
| $(`#displayJobNameHref`).attr("href",href) | |||||
| $(`#displayJobNameHref`).attr("title",obj[key]) | |||||
| $(`#${key}`).text(obj[key]) | |||||
| let versionName = obj["trainJobVersionName"] | |||||
| if(versionName!=""){ | |||||
| let html = `<span style="margin-left:1rem" class="ui label">${versionName}</span>` | |||||
| $('#displayJobName').append(html) | |||||
| } | |||||
| } | |||||
| else if(key==="parameters"){ | |||||
| if(obj[key]==='--'){ | |||||
| $(`#${key}`).text(obj[key]) | |||||
| }else{ | |||||
| const parameterArray = obj[key].map(element => { | |||||
| let labelValue = `${element.label}=${element.value}` | |||||
| return labelValue | |||||
| }); | |||||
| const parameter = parameterArray.join('; ') | |||||
| $(`#${key}`).text(parameter) | |||||
| $(`#${key}`).attr("title",parameter) | |||||
| } | |||||
| } | |||||
| else{ | |||||
| $(`#${key}`).text(obj[key]) | |||||
| $(`#${key}`).attr("title",obj[key]) | |||||
| } | |||||
| } | |||||
| for(let key in accObj){ | |||||
| $(`#${key}`).text(accObj[key]) | |||||
| $(`#${key}`).attr("title",accObj[key]) | |||||
| } | |||||
| } | |||||
| function loadModelFile(ID,version_name,parents,filename,init){ | |||||
| $.get(`${url}query_onelevel_modelfile?ID=${ID}&parentDir=${parents}`, (data) => { | |||||
| $('#dir_list').empty() | |||||
| renderDir(data,ID,version_name) | |||||
| if(init==="init"){ | |||||
| $('input[name=model]').val("") | |||||
| $('input[name=modelback]').val(version_name) | |||||
| $('#file_breadcrumb').empty() | |||||
| let htmlBread = "" | |||||
| htmlBread += `<div class='active section'>${version_name}</div>` | |||||
| htmlBread += "<div class='divider'> / </div>" | |||||
| $('#file_breadcrumb').append(htmlBread) | |||||
| }else{ | |||||
| renderBrend(ID,version_name,parents,filename,init) | |||||
| } | |||||
| }) | |||||
| } | |||||
| function renderSize(value){ | |||||
| if(null==value||value==''){ | |||||
| return "0 Bytes"; | |||||
| } | |||||
| var unitArr = new Array("Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"); | |||||
| var index=0; | |||||
| var srcsize = parseFloat(value); | |||||
| index=Math.floor(Math.log(srcsize)/Math.log(1024)); | |||||
| var size =srcsize/Math.pow(1024,index); | |||||
| size=size.toFixed(2);//保留的小数位数 | |||||
| return size+unitArr[index]; | |||||
| } | |||||
| function renderBrend(ID,version_name,parents,filename,init){ | |||||
| if(init=="folder"){ | |||||
| let htmlBrend = "" | |||||
| let sectionName=$('#file_breadcrumb .active.section').text() | |||||
| let parents1 = $('input[name=model]').val() | |||||
| let filename1 = $('input[name=modelback]').val() | |||||
| if(parents1===""){ | |||||
| $('#file_breadcrumb .active.section').replaceWith(`<a class='section' onclick="loadModelFile('${ID}','${version_name}','${parents1}','','init')">${sectionName}</a>`) | |||||
| }else{ | |||||
| $('#file_breadcrumb .active.section').replaceWith(`<a class='section' onclick="loadModelFile('${ID}','${version_name}','${parents1}','${filename1}')">${sectionName}</a>`) | |||||
| } | |||||
| htmlBrend += `<div class='active section'>${filename}</div>` | |||||
| htmlBrend += "<div class='divider'> / </div>" | |||||
| $('#file_breadcrumb').append(htmlBrend) | |||||
| $('input[name=model]').val(parents) | |||||
| $('input[name=modelback]').val(filename) | |||||
| }else{ | |||||
| $('input[name=model]').val(parents) | |||||
| $('input[name=modelback]').val(filename) | |||||
| let selectEle = $('#file_breadcrumb a.section').filter( | |||||
| (index, item) => { | |||||
| return item.text == filename; | |||||
| } | |||||
| ); | |||||
| selectEle.nextAll().remove(); | |||||
| selectEle.after("<div class='divider'> / </div>"); | |||||
| selectEle.replaceWith(`<div class='active section'>${filename}</div>`); | |||||
| } | |||||
| } | |||||
| function renderDir(data,ID,version_name){ | |||||
| let html="" | |||||
| html += "<div class='ui grid' style='margin:0;'>" | |||||
| html += "<div class='row' style='padding: 0;'>" | |||||
| html += "<div class='ui sixteen wide column' style='padding:1rem;'>" | |||||
| html += "<div class='dir list'>" | |||||
| html += "<table id='repo-files-table' class='ui single line table pad20'>" | |||||
| html += '<tbody>' | |||||
| for(let i=0;i<data.length;i++){ | |||||
| let dirs_size = renderSize(data[i].Size) | |||||
| html += "<tr>" | |||||
| html += "<td class='name six wid'>" | |||||
| html += "<span class='truncate'>" | |||||
| html += "<span class='octicon octicon-file-directory'>" | |||||
| html += "</span>" | |||||
| if(data[i].IsDir){ | |||||
| html += `<a onclick="loadModelFile('${ID}','${version_name}','${data[i].ParenDir}','${data[i].FileName}','folder')">` | |||||
| html += "<span class='fitted'><i class='folder icon' width='16' height='16' aria-hidden='true'></i>" + data[i].FileName + "</span>" | |||||
| }else{ | |||||
| html += `<a href="${url}${ID}/downloadsingle?parentDir=${data[i].ParenDir}&fileName=${data[i].FileName}">` | |||||
| html += "<span class='fitted'><i class='file icon' width='16' height='16' aria-hidden='true'></i>" + data[i].FileName + "</span>" | |||||
| } | |||||
| html += '</a>' | |||||
| html += "</span>" | |||||
| html += "</td>" | |||||
| html += "<td class='message seven wide'>" | |||||
| if(data[i].IsDir){ | |||||
| html += "<span class='truncate has-emoji'></span>" | |||||
| }else{ | |||||
| html += "<span class='truncate has-emoji'>"+ `${dirs_size}` + "</span>" | |||||
| } | |||||
| html += "</td>" | |||||
| html += "<td class='text right age three wide'>" | |||||
| html += "<span class='truncate has-emoji'>" + data[i].ModTime + "</span>" | |||||
| html += "</td>" | |||||
| html += "</tr>" | |||||
| } | |||||
| html += "</tbody>" | |||||
| html += "</table>" | |||||
| html += "</div>" | |||||
| html += "</div>" | |||||
| html += "</div>" | |||||
| html += "</div>" | |||||
| $('#dir_list').append(html) | |||||
| } | |||||
| </script> | |||||
| @@ -861,7 +861,8 @@ | |||||
| $('td.ti-text-form-content.spec div').text(specStr); | $('td.ti-text-form-content.spec div').text(specStr); | ||||
| SPEC && $('td.ti-text-form-content.resorce_type div').text(getListValueWithKey(ACC_CARD_TYPE, SPEC.AccCardType)); | SPEC && $('td.ti-text-form-content.resorce_type div').text(getListValueWithKey(ACC_CARD_TYPE, SPEC.AccCardType)); | ||||
| } | } | ||||
| var oLogHref = $('#-log-down').attr('href'); | |||||
| var repoPath = {{$.RepoRelPath}}; | |||||
| var oLogHref = `/api/v1/repos/${repoPath}/cloudbrain`; | |||||
| $('#-log-down').attr('href', oLogHref + `/${res.ID}/download_log_file`); | $('#-log-down').attr('href', oLogHref + `/${res.ID}/download_log_file`); | ||||
| $('.full-log-dialog').attr('data-href', oLogHref + `/${res.ID}/download_log_file`); | $('.full-log-dialog').attr('data-href', oLogHref + `/${res.ID}/download_log_file`); | ||||
| if (res.ResultJson) { | if (res.ResultJson) { | ||||
| @@ -65,7 +65,7 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{range .Tasks}} | |||||
| {{range .Tasks}} | |||||
| {{if .Repo}} | {{if .Repo}} | ||||
| <div class="ui grid stackable item"> | <div class="ui grid stackable item"> | ||||
| <div class="row"> | <div class="row"> | ||||
| @@ -155,7 +155,7 @@ | |||||
| <!-- 智算中心 --> | <!-- 智算中心 --> | ||||
| <div class="one wide column text center nowrap" style="width:8% !important;"> | <div class="one wide column text center nowrap" style="width:8% !important;"> | ||||
| <span style="font-size: 12px;" class="aicenter_{{.DisplayJobName}}_{{$JobID}}">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span> | |||||
| <span style="font-size: 12px;" class="aicenter_{{.DisplayJobName}}_{{$JobID}}" title="{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span> | |||||
| </div> | </div> | ||||
| <!-- XPU类型 --> | <!-- XPU类型 --> | ||||
| <div class="one wide column text center nowrap" style="width:10% !important;"> | <div class="one wide column text center nowrap" style="width:10% !important;"> | ||||
| @@ -169,16 +169,16 @@ | |||||
| spanEl.setAttribute('title', cardType); | spanEl.setAttribute('title', cardType); | ||||
| spanEl.innerText = cardType; | spanEl.innerText = cardType; | ||||
| var cluster = spec.Cluster || '--'; | |||||
| var cluster = {{.Cluster}} || '--'; | |||||
| var clusterName = document.querySelector('.cloudbrain_debug').dataset['cluster' + cluster[0] + cluster.toLocaleLowerCase().slice(1)] || '--'; | var clusterName = document.querySelector('.cloudbrain_debug').dataset['cluster' + cluster[0] + cluster.toLocaleLowerCase().slice(1)] || '--'; | ||||
| spanEl = document.querySelector('.cluster_{{.DisplayJobName}}_{{$JobID}}'); | spanEl = document.querySelector('.cluster_{{.DisplayJobName}}_{{$JobID}}'); | ||||
| spanEl.setAttribute('title', cluster); | spanEl.setAttribute('title', cluster); | ||||
| spanEl.innerText = clusterName; | spanEl.innerText = clusterName; | ||||
| var aiCenter = spec.AiCenterName || '--'; | |||||
| spanEl = document.querySelector('.aicenter_{{.DisplayJobName}}_{{$JobID}}'); | |||||
| spanEl.setAttribute('title', aiCenter); | |||||
| spanEl.innerText = aiCenter; | |||||
| // var aiCenter = spec.AiCenterName || '--'; | |||||
| // spanEl = document.querySelector('.aicenter_{{.DisplayJobName}}_{{$JobID}}'); | |||||
| // spanEl.setAttribute('title', aiCenter); | |||||
| // spanEl.innerText = aiCenter; | |||||
| })(); | })(); | ||||
| </script> | </script> | ||||
| <!-- 项目 --> | <!-- 项目 --> | ||||
| @@ -16,16 +16,17 @@ | |||||
| prop="name" | prop="name" | ||||
| :label="i18n.model_name" | :label="i18n.model_name" | ||||
| align="left" | align="left" | ||||
| min-width="17%" | |||||
| min-width="20%" | |||||
| > | > | ||||
| <template slot-scope="scope"> | <template slot-scope="scope"> | ||||
| <div class="expand-icon" v-if="scope.row.hasChildren === false"> | <div class="expand-icon" v-if="scope.row.hasChildren === false"> | ||||
| <i class="el-icon-arrow-right"></i> | <i class="el-icon-arrow-right"></i> | ||||
| </div> | </div> | ||||
| <!-- <i class="el-icon-time"></i> --> | <!-- <i class="el-icon-time"></i> --> | ||||
| <span v-if="!scope.row.Children" :class="scope.row.modelType == '1' ? 'm-local' : 'm-online'">{{ scope.row.modelType == '1' ? i18n.local : i18n.online }}</span> | |||||
| <a | <a | ||||
| class="text-over" | class="text-over" | ||||
| :href="showinfoHref + scope.row.name" | |||||
| :href="showinfoHref + encodeURIComponent(scope.row.name)" | |||||
| :title="scope.row.name" | :title="scope.row.name" | ||||
| >{{ scope.row.name }}</a | >{{ scope.row.name }}</a | ||||
| > | > | ||||
| @@ -131,12 +132,12 @@ | |||||
| <el-table-column | <el-table-column | ||||
| :label="i18n.model_operation" | :label="i18n.model_operation" | ||||
| min-width="17%" | |||||
| min-width="15%" | |||||
| align="center" | align="center" | ||||
| > | > | ||||
| <template slot-scope="scope"> | <template slot-scope="scope"> | ||||
| <div class="space-around"> | |||||
| <a | |||||
| <div class="space-around" > | |||||
| <!--<a | |||||
| :style="{ | :style="{ | ||||
| visibility: !scope.row.Children ? 'visible' : 'hidden', | visibility: !scope.row.Children ? 'visible' : 'hidden', | ||||
| }" | }" | ||||
| @@ -149,19 +150,23 @@ | |||||
| ) | ) | ||||
| " | " | ||||
| >{{ i18n.model_create_new_ver }}</a | >{{ i18n.model_create_new_ver }}</a | ||||
| > | |||||
| <a | |||||
| >--> | |||||
| <a class="op-btn" | |||||
| v-show="scope.row.modelType == 1" | |||||
| :href="url + 'create_local_model_1?type=1&name=' + encodeURIComponent(scope.row.name) + '&id=' + scope.row.id" | |||||
| :class="{ disabled: !scope.row.isCanOper }" | |||||
| >{{ i18n.modify }}</a> | |||||
| <a class="op-btn" v-show="scope.row.modelType != 1" style="color:transparent;cursor:default;" >{{ i18n.modify }}</a> | |||||
| <a class="op-btn" | |||||
| :href="loadhref + scope.row.id" | :href="loadhref + scope.row.id" | ||||
| :class="{ disabled: !scope.row.isCanOper }" | :class="{ disabled: !scope.row.isCanOper }" | ||||
| >{{ i18n.model_download }}</a | |||||
| > | |||||
| <a | |||||
| >{{ i18n.model_download }}</a> | |||||
| <a class="op-btn" | |||||
| :class="{ disabled: !scope.row.isCanDelete }" | :class="{ disabled: !scope.row.isCanDelete }" | ||||
| @click=" | @click=" | ||||
| deleteModel(scope.row.id, scope.row.cName, scope.row.rowKey) | deleteModel(scope.row.id, scope.row.cName, scope.row.rowKey) | ||||
| " | " | ||||
| >{{ i18n.model_delete }}</a | |||||
| > | |||||
| >{{ i18n.model_delete }}</a> | |||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| </el-table-column> | </el-table-column> | ||||
| @@ -223,9 +228,10 @@ export default { | |||||
| let tableData; | let tableData; | ||||
| tableData = res.data; | tableData = res.data; | ||||
| for (let i = 0; i < tableData.length; i++) { | for (let i = 0; i < tableData.length; i++) { | ||||
| trainTaskInfo = JSON.parse(tableData[i].trainTaskInfo); | |||||
| trainTaskInfo = JSON.parse(tableData[i].trainTaskInfo || '{}'); | |||||
| tableData[i].engineName = this.getEngineName(tableData[i]); | tableData[i].engineName = this.getEngineName(tableData[i]); | ||||
| tableData[i].computeResource = trainTaskInfo.ComputeResource; | |||||
| // tableData[i].computeResource = trainTaskInfo.ComputeResource; | |||||
| tableData[i].computeResource = tableData[i].type == '0' ? 'CPU/GPU' : 'NPU'; | |||||
| tableData[i].cName = tableData[i].name; | tableData[i].cName = tableData[i].name; | ||||
| tableData[i].rowKey = tableData[i].id + Math.random(); | tableData[i].rowKey = tableData[i].id + Math.random(); | ||||
| tableData[i].name = ""; | tableData[i].name = ""; | ||||
| @@ -474,7 +480,7 @@ export default { | |||||
| try { | try { | ||||
| this.loadNodeMap.clear(); | this.loadNodeMap.clear(); | ||||
| this.$axios | this.$axios | ||||
| .get(location.href + "_api", { | |||||
| .get(this.url + "show_model_api", { | |||||
| params: this.params, | params: this.params, | ||||
| }) | }) | ||||
| .then((res) => { | .then((res) => { | ||||
| @@ -483,15 +489,15 @@ export default { | |||||
| let trainTaskInfo; | let trainTaskInfo; | ||||
| this.tableData = res.data.data; | this.tableData = res.data.data; | ||||
| for (let i = 0; i < this.tableData.length; i++) { | for (let i = 0; i < this.tableData.length; i++) { | ||||
| trainTaskInfo = JSON.parse(this.tableData[i].trainTaskInfo); | |||||
| trainTaskInfo = JSON.parse(this.tableData[i].trainTaskInfo || '{}'); | |||||
| this.tableData[i].cName = this.tableData[i].name; | this.tableData[i].cName = this.tableData[i].name; | ||||
| this.tableData[i].rowKey = this.tableData[i].id + Math.random(); | this.tableData[i].rowKey = this.tableData[i].id + Math.random(); | ||||
| this.tableData[i].engineName = this.getEngineName( | this.tableData[i].engineName = this.getEngineName( | ||||
| this.tableData[i] | this.tableData[i] | ||||
| ); | ); | ||||
| this.tableData[i].computeResource = trainTaskInfo.ComputeResource; | |||||
| this.tableData[i].hasChildren = | |||||
| res.data.data[i].versionCount === 1 ? false : true; | |||||
| // this.tableData[i].computeResource = trainTaskInfo.ComputeResource; | |||||
| this.tableData[i].computeResource = this.tableData[i].type == '0' ? 'CPU/GPU' : 'NPU'; | |||||
| this.tableData[i].hasChildren = res.data.data[i].versionCount === 1 ? false : true; | |||||
| if (this.tableData[i].status !== 1) { | if (this.tableData[i].status !== 1) { | ||||
| countStatus++; | countStatus++; | ||||
| } | } | ||||
| @@ -615,6 +621,24 @@ export default { | |||||
| white-space: nowrap; | white-space: nowrap; | ||||
| } | } | ||||
| .m-local { | |||||
| background-color: rgb(22, 132, 252); | |||||
| color: white; | |||||
| padding: 2px 3px; | |||||
| border-radius: 4px; | |||||
| font-size: 12px; | |||||
| margin-right: 2px; | |||||
| } | |||||
| .m-online { | |||||
| background-color: rgb(91, 185, 115); | |||||
| color: white; | |||||
| padding: 2px 3px; | |||||
| border-radius: 4px; | |||||
| font-size: 12px; | |||||
| margin-right: 2px; | |||||
| } | |||||
| .el-icon-arrow-right { | .el-icon-arrow-right { | ||||
| font-family: element-icons !important; | font-family: element-icons !important; | ||||
| speak: none; | speak: none; | ||||
| @@ -677,6 +701,15 @@ export default { | |||||
| justify-content: space-around; | justify-content: space-around; | ||||
| } | } | ||||
| .op-btn-c { | |||||
| text-align: right; | |||||
| padding-right: 20px; | |||||
| } | |||||
| .op-btn { | |||||
| margin: 0 0 0 5px; | |||||
| } | |||||
| .disabled { | .disabled { | ||||
| cursor: default; | cursor: default; | ||||
| pointer-events: none; | pointer-events: none; | ||||
| @@ -1,6 +1,6 @@ | |||||
| <template> | <template> | ||||
| <el-dialog :close-on-click-modal="!deleteLoading" v-dlg-drag :title="dialogTitle" :visible.sync="deleteDialog"> | |||||
| <el-dialog :close-on-click-modal="!deleteLoading" :title="dialogTitle" :visible.sync="deleteDialog"> | |||||
| <div class="message-box__content"> | <div class="message-box__content"> | ||||
| @@ -411,7 +411,7 @@ export default async function initCloudrain() { | |||||
| $(`#${jobName}`).popup("toggle"); | $(`#${jobName}`).popup("toggle"); | ||||
| } else { | } else { | ||||
| let versionData = data.filter((item) => { | let versionData = data.filter((item) => { | ||||
| return item.Version === versionName; | |||||
| return item.version === versionName; | |||||
| }); | }); | ||||
| if (versionData.length == 0) { | if (versionData.length == 0) { | ||||
| $(`#${jobName}`).popup("toggle"); | $(`#${jobName}`).popup("toggle"); | ||||
| @@ -105,6 +105,9 @@ export const i18nVue = { | |||||
| file_sync_fail:"文件同步失败", | file_sync_fail:"文件同步失败", | ||||
| no_file_to_download:"没有文件可以下载", | no_file_to_download:"没有文件可以下载", | ||||
| task_not_finished:"任务还未结束,稍后再来看看", | task_not_finished:"任务还未结束,稍后再来看看", | ||||
| local:"本地", | |||||
| online:"线上", | |||||
| modify:"修改", | |||||
| }, | }, | ||||
| US: { | US: { | ||||
| computer_vision: "computer vision", | computer_vision: "computer vision", | ||||
| @@ -216,5 +219,8 @@ export const i18nVue = { | |||||
| file_sync_fail:"File synchronization failed", | file_sync_fail:"File synchronization failed", | ||||
| no_file_to_download:"No files can be downloaded", | no_file_to_download:"No files can be downloaded", | ||||
| task_not_finished:"Task not finished yet, please wait", | task_not_finished:"Task not finished yet, please wait", | ||||
| local:"Local", | |||||
| online:"Online", | |||||
| modify:"Modify", | |||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -6,8 +6,10 @@ import "./publicpath.js"; | |||||
| import "./polyfills.js"; | import "./polyfills.js"; | ||||
| import "./features/letteravatar.js"; | import "./features/letteravatar.js"; | ||||
| import Vue from "vue"; | import Vue from "vue"; | ||||
| import ElementUI from "element-ui"; | |||||
| import "element-ui/lib/theme-chalk/index.css"; | import "element-ui/lib/theme-chalk/index.css"; | ||||
| import localeEn from 'element-ui/lib/locale/lang/en'; | |||||
| import localeZh from 'element-ui/lib/locale/lang/zh-CN'; | |||||
| import ElementUI from "element-ui"; | |||||
| import axios from "axios"; | import axios from "axios"; | ||||
| import qs from "qs"; | import qs from "qs"; | ||||
| import Cookies from "js-cookie"; | import Cookies from "js-cookie"; | ||||
| @@ -56,15 +58,19 @@ import './features/ad.js'; | |||||
| import { Fancybox } from "./vendor/fancybox.esm.js"; | import { Fancybox } from "./vendor/fancybox.esm.js"; | ||||
| Vue.use(ElementUI); | |||||
| Vue.prototype.$axios = axios; | Vue.prototype.$axios = axios; | ||||
| Vue.prototype.$Cookies = Cookies; | Vue.prototype.$Cookies = Cookies; | ||||
| Vue.prototype.qs = qs; | Vue.prototype.qs = qs; | ||||
| Vue.prototype.$message = Message; | Vue.prototype.$message = Message; | ||||
| Vue.prototype.$locale = i18nVue; | Vue.prototype.$locale = i18nVue; | ||||
| window.i18n = i18nVue[document.querySelector('html').getAttribute('lang') == 'zh-CN' ? 'CN' : 'US']; | |||||
| const lang = document.querySelector('html').getAttribute('lang'); | |||||
| window.i18n = i18nVue[lang == 'zh-CN' ? 'CN' : 'US']; | |||||
| const { AppSubUrl, StaticUrlPrefix, csrf } = window.config; | const { AppSubUrl, StaticUrlPrefix, csrf } = window.config; | ||||
| Vue.use(ElementUI, { | |||||
| locale: lang === 'zh-CN' ? localeZh : localeEn, | |||||
| }); | |||||
| Object.defineProperty(Vue.prototype, "$echarts", { | Object.defineProperty(Vue.prototype, "$echarts", { | ||||
| value: echarts, | value: echarts, | ||||
| }); | }); | ||||
| @@ -5071,12 +5077,7 @@ function initcreateRepo() { | |||||
| initcreateRepo(); | initcreateRepo(); | ||||
| function initChartsNpu() { | function initChartsNpu() { | ||||
| const url = window.location.href; | |||||
| const urlArr = url.split("/"); | |||||
| let userName = urlArr.slice(-5)[0]; | |||||
| let repoPath = urlArr.slice(-4)[0]; | |||||
| let jobID = urlArr.slice(-1)[0]; | |||||
| const repoPath = $('.metric_chart').data('path') | |||||
| let options = { | let options = { | ||||
| legend: { | legend: { | ||||
| data: [], | data: [], | ||||
| @@ -5127,7 +5128,7 @@ function initChartsNpu() { | |||||
| document.getElementById(`metric-${versionName}`) | document.getElementById(`metric-${versionName}`) | ||||
| ); | ); | ||||
| $.get( | $.get( | ||||
| `${window.config.AppSubUrl}/api/v1/repos/${userName}/${repoPath}/modelarts/train-job/${jobID}/metric_statistics?version_name=${versionName}&statistic_type=each&metrics=`, | |||||
| `${window.config.AppSubUrl}/api/v1/repos/${repoPath}`, | |||||
| (res) => { | (res) => { | ||||
| let filterDta = res.MetricsInfo.filter((item) => { | let filterDta = res.MetricsInfo.filter((item) => { | ||||
| return ![ | return ![ | ||||
| @@ -0,0 +1,106 @@ | |||||
| import service from "../service"; | |||||
| import Qs from 'qs'; | |||||
| // 保存本地模型 | |||||
| export const saveLocalModel = (data) => { | |||||
| return service({ | |||||
| url: `${data.repo}/modelmanage/create_local_model`, | |||||
| method: 'post', | |||||
| headers: { 'Content-type': 'application/x-www-form-urlencoded' }, | |||||
| params: {}, | |||||
| data: Qs.stringify(data), | |||||
| }); | |||||
| }; | |||||
| // 修改模型 | |||||
| // data: {id,type,name,version,engine,label,description:} | |||||
| export const modifyModel = (data) => { | |||||
| return service({ | |||||
| url: `${data.repo}/modelmanage/modify_model`, | |||||
| method: 'put', | |||||
| headers: { 'Content-type': 'application/x-www-form-urlencoded' }, | |||||
| params: {}, | |||||
| data: Qs.stringify(data), | |||||
| }); | |||||
| }; | |||||
| // 求模型信息 | |||||
| export const getModelInfoByName = (params) => { | |||||
| return service({ | |||||
| url: `${params.repo}/modelmanage/show_model_info_api`, | |||||
| method: 'get', | |||||
| params, | |||||
| data: {}, | |||||
| }); | |||||
| }; | |||||
| // 求模型中文件列表 | |||||
| // params {repo, ID, parentDir} | |||||
| export const getModelFiles = (params) => { | |||||
| return service({ | |||||
| url: `${params.repo}/modelmanage/query_onelevel_modelfile`, | |||||
| method: 'get', | |||||
| params, | |||||
| data: {}, | |||||
| }); | |||||
| }; | |||||
| // 删除模型文件 | |||||
| // params {repo, id, fileName} | |||||
| export const deleteModelFile = (params) => { | |||||
| return service({ | |||||
| url: `${params.repo}/modelmanage/delete_model_file`, | |||||
| method: 'delete', | |||||
| params, | |||||
| data: {}, | |||||
| }); | |||||
| }; | |||||
| /* 文件上传相关 */ | |||||
| // 上传文件1: 获取文件chunks信息 | |||||
| // params: { md5, type: 0-CPU/GPU,1-NPU, file_name, scene: 'model', modeluuid } | |||||
| // return: uploadID, uuid, uploaded, chunks, attachID, modeluuid, modelName, fileName | |||||
| export const getChunks = (params) => { | |||||
| return service({ | |||||
| url: `/attachments/model/get_chunks`, | |||||
| method: 'get', | |||||
| params, | |||||
| data: {}, | |||||
| }); | |||||
| }; | |||||
| // 上传文件2: 上传新文件 | |||||
| // params: { totalChunkCounts, md5, size, fileType, type, file_name, scene=model, modeluuid=xxxx } | |||||
| // return: uploadID, uuid | |||||
| export const getNewMultipart = (params) => { | |||||
| return service({ | |||||
| url: `/attachments/model/new_multipart`, | |||||
| method: 'get', | |||||
| params, | |||||
| data: {}, | |||||
| }); | |||||
| }; | |||||
| // 上传文件3: 获取分片上传地址 | |||||
| // params: { uuid, uploadID, size, chunkNumber, type, file_name, scene=model } | |||||
| // return: url | |||||
| export const getMultipartUrl = (params) => { | |||||
| return service({ | |||||
| url: `/attachments/model/get_multipart_url`, | |||||
| method: 'get', | |||||
| params, | |||||
| data: {}, | |||||
| }); | |||||
| }; | |||||
| // 上传文件4: 完成上传后 | |||||
| // data: { uuid, uploadID, size, type, file_name, dataset_id, description, scene=model, modeluuid=xxxx } | |||||
| export const setCompleteMultipart = (data) => { | |||||
| return service({ | |||||
| url: `/attachments/model/complete_multipart`, | |||||
| method: 'post', | |||||
| headers: { 'Content-type': 'application/x-www-form-urlencoded' }, | |||||
| params: {}, | |||||
| data: Qs.stringify(data), | |||||
| }); | |||||
| }; | |||||
| @@ -110,6 +110,19 @@ export const getResSpecificationList = (params) => { | |||||
| }); | }); | ||||
| } | } | ||||
| // 查询资源规格列表(所有) | |||||
| // cluster 所属集群 :OpenI 启智集群,C2Net 智算集群 | |||||
| // queue 所属队列id | |||||
| // status 状态 : 1 待审核 2已上架 3已下架 | |||||
| export const getResSpecificationListAll = (params) => { | |||||
| return service({ | |||||
| url: '/admin/resources/specification/list/all', | |||||
| method: 'get', | |||||
| params, | |||||
| data: {}, | |||||
| }); | |||||
| } | |||||
| // 同步智算网络资源池(队列) | // 同步智算网络资源池(队列) | ||||
| export const syncResSpecification = () => { | export const syncResSpecification = () => { | ||||
| return service({ | return service({ | ||||
| @@ -14,3 +14,6 @@ export const AI_CENTER = [{ k: 'OpenIOne', v: i18n.t('resourcesManagement.OpenIO | |||||
| export const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'GPU' }, { k: 'NPU', v: 'NPU' }, { k: 'MLU', v: 'MLU' }]; | export const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'GPU' }, { k: 'NPU', v: 'NPU' }, { k: 'MLU', v: 'MLU' }]; | ||||
| export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'ASCEND910', v: 'Ascend 910' }, { k: 'MLU270', v: 'MLU270' }, { k: 'RTX3080', v: 'RTX3080' }]; | export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'ASCEND910', v: 'Ascend 910' }, { k: 'MLU270', v: 'MLU270' }, { k: 'RTX3080', v: 'RTX3080' }]; | ||||
| export const SPECIFICATION_STATUS = [{ k: '1', v: i18n.t('resourcesManagement.willOnShelf') }, { k: '2', v: i18n.t('resourcesManagement.onShelf') }, { k: '3', v: i18n.t('resourcesManagement.offShelf') }]; | export const SPECIFICATION_STATUS = [{ k: '1', v: i18n.t('resourcesManagement.willOnShelf') }, { k: '2', v: i18n.t('resourcesManagement.onShelf') }, { k: '3', v: i18n.t('resourcesManagement.offShelf') }]; | ||||
| // 模型 | |||||
| export const MODEL_ENGINES = [{ k: '0', v: 'PyTorch' }, { k: '1', v: 'TensorFlow' }, { k: '2', v: 'MindSpore' }, { k: '4', v: 'PaddlePaddle' }, { k: '5', v: 'OneFlow' }, { k: '6', v: 'MXNet' }, { k: '3', v: 'Other' }]; | |||||
| @@ -157,7 +157,7 @@ const en = { | |||||
| computeCluster: 'Compute Cluster', | computeCluster: 'Compute Cluster', | ||||
| resourceSpecification: 'Resource Specification', | resourceSpecification: 'Resource Specification', | ||||
| lastUpdateTime: 'Last Update Time', | lastUpdateTime: 'Last Update Time', | ||||
| resSceneDeleteConfirm: 'Are you sure to delete the current Resource Scene?', | |||||
| resSceneDeleteConfirm: 'Are you sure to delete the current Resource Scene?', | |||||
| resourceSpecificationIsAvailable: 'Specification Is Available', | resourceSpecificationIsAvailable: 'Specification Is Available', | ||||
| resourceSpecificationIsAvailableAll: 'Specification Is Available(All)', | resourceSpecificationIsAvailableAll: 'Specification Is Available(All)', | ||||
| available: 'Available', | available: 'Available', | ||||
| @@ -187,7 +187,7 @@ const en = { | |||||
| onlyFace:'Only face', | onlyFace:'Only face', | ||||
| onlyLicensePlate:'Only license plate', | onlyLicensePlate:'Only license plate', | ||||
| dragThePictureHere:'Drag the picture here', | dragThePictureHere:'Drag the picture here', | ||||
| or:'or', | |||||
| or:' or ', | |||||
| clickUpload:'Click upload', | clickUpload:'Click upload', | ||||
| dataDesensitizationModelExperience:'Data desensitization model experience', | dataDesensitizationModelExperience:'Data desensitization model experience', | ||||
| dataDesensitizationModelDesc:'Use AI technology to desensitize the face and license plate number in the picture. For more information about this model, please visit the project', | dataDesensitizationModelDesc:'Use AI technology to desensitize the face and license plate number in the picture. For more information about this model, please visit the project', | ||||
| @@ -219,7 +219,68 @@ const en = { | |||||
| graphicMemory: "Graphic Memory", | graphicMemory: "Graphic Memory", | ||||
| memory: "Memory", | memory: "Memory", | ||||
| sharedMemory: "Shared Memory", | sharedMemory: "Shared Memory", | ||||
| tips:'The newly created debugging task will be placed in the project openi-notebook under your name. If there is no such project, the system will automatically create a new one.' | |||||
| tips: 'The newly created debugging task will be placed in the project openi-notebook under your name. If there is no such project, the system will automatically create a new one.' | |||||
| }, | |||||
| modelManage: { | |||||
| modelManage: 'Model management', | |||||
| modelName: 'Model name', | |||||
| useCluster: 'Available clusters', | |||||
| local: 'Local', | |||||
| online: 'Online', | |||||
| createModel: 'Create Model', | |||||
| importLocalModel: 'Import Lacal Model', | |||||
| importOnlineModel: 'Import Online Model', | |||||
| modifyModelInfo: 'Modify model information', | |||||
| addModelFiles: 'Add model files', | |||||
| uploadModelFiles: 'Upload model files', | |||||
| pleaseInputModelName: 'Please input model name', | |||||
| version: 'Version', | |||||
| modelEngine: 'Model engine', | |||||
| modelLabel: 'Model label', | |||||
| modelLabelInputTips: 'Input labels, multiple labels are separated by spaces', | |||||
| modelDescr: 'Model description', | |||||
| modelDescrInputTips: 'The description should not exceed 256 characters', | |||||
| confirm: 'Confirm', | |||||
| cancel: 'Cancel', | |||||
| modelCreateFailed: 'Model create failed', | |||||
| modelModifyFailed: 'Model modify failed', | |||||
| fileUpload: 'File upload', | |||||
| upload: 'Upload', | |||||
| uploadStatus: 'Upload status', | |||||
| modelFileUploadDefaultTips: 'Click to add files or drag files here directly', | |||||
| modelFileUploadErrTips: 'Up to 10 files can be uploaded at a time, and the total file size of the model does not exceed {size}GB', | |||||
| modelFileNameTips: 'The file name should not exceed 128 characters', | |||||
| fileIstoBig: 'File is to big', | |||||
| removeFile: 'Rmove file', | |||||
| uploadSuccess: 'upload success', | |||||
| uploadFailed: 'upload failed', | |||||
| calcFileMd5: 'Calculating file MD5...', | |||||
| uploading: 'Uploading...', | |||||
| fileHasAlreadyInTheModel: 'This file has already in the model: ', | |||||
| basicInfo: 'Basic information', | |||||
| modelSize: 'Model size', | |||||
| descr: 'Description', | |||||
| createTime: 'Create Time', | |||||
| label: 'Label', | |||||
| trainTaskInfo: 'Train task information', | |||||
| trainTask: 'Train task', | |||||
| codeBranch: 'Code branch', | |||||
| bootFile: 'Boot file', | |||||
| trainDataset: 'Train dataset', | |||||
| specInfo: 'Specifications', | |||||
| workServerNumber: 'Amount of compute node', | |||||
| runParameters: 'Run parameters', | |||||
| seeMore: 'View more', | |||||
| collapseDetails: 'Collapse details', | |||||
| modelFilesList: 'Mode files list', | |||||
| fileName: 'File name', | |||||
| fileSize: 'File size', | |||||
| updateTime: 'Upate Time', | |||||
| operate: 'Operation', | |||||
| delete: 'Delete', | |||||
| infoModificationFailed: 'Information modify failed', | |||||
| deleteModelFileConfirmTips: 'Are you sure you want to delete the current model file?', | |||||
| modelFileDeleteFailed: 'Model file delete failed', | |||||
| }, | }, | ||||
| } | } | ||||
| @@ -222,6 +222,69 @@ const zh = { | |||||
| sharedMemory: "共享内存", | sharedMemory: "共享内存", | ||||
| tips:'本次新建的调试任务会放在您名下项目openi-notebook中,如果没有该项目系统会自动新建一个。' | tips:'本次新建的调试任务会放在您名下项目openi-notebook中,如果没有该项目系统会自动新建一个。' | ||||
| }, | }, | ||||
| modelManage: { | |||||
| modelManage: '模型管理', | |||||
| modelName: '模型名称', | |||||
| useCluster: '可用集群', | |||||
| local: '本地', | |||||
| online: '线上', | |||||
| createModel: '创建模型', | |||||
| importLocalModel: '导入本地模型', | |||||
| importOnlineModel: '导入线上模型', | |||||
| modifyModelInfo: '修改模型信息', | |||||
| addModelFiles: '增加模型文件', | |||||
| uploadModelFiles: '上传模型文件', | |||||
| pleaseInputModelName: '请输入模型名称', | |||||
| version: '版本', | |||||
| modelEngine: '模型框架', | |||||
| modelLabel: '模型标签', | |||||
| modelLabelInputTips: '输入标签,多个标签用空格区分', | |||||
| modelDescr: '模型描述', | |||||
| modelDescrInputTips: '描述字数不超过255个字符', | |||||
| confirm: '确定', | |||||
| cancel: '取消', | |||||
| modelCreateFailed: '模型创建失败', | |||||
| modelModifyFailed: '模型修改失败', | |||||
| fileUpload: '文件上传', | |||||
| upload: '上传', | |||||
| uploadStatus: '上传状态', | |||||
| modelFileUploadDefaultTips: '点击添加文件或直接拖拽文件到此处', | |||||
| modelFileUploadErrTips: '单次最多上传10个文件,模型总文件大小不超过{size}G', | |||||
| modelFileNameTips: '文件名长度不超过128个字符', | |||||
| fileIstoBig: '文件太大', | |||||
| removeFile: '移除文件', | |||||
| uploadSuccess: '上传成功', | |||||
| uploadFailed: '上传失败', | |||||
| calcFileMd5: '计算文件MD5...', | |||||
| uploading: '上传中...', | |||||
| fileHasAlreadyInTheModel: '该文件已上传在模型:', | |||||
| basicInfo: '基本信息', | |||||
| modelSize: '模型大小', | |||||
| descr: '描述', | |||||
| createTime: '创建时间', | |||||
| label: '标签', | |||||
| trainTaskInfo: '训练相关信息', | |||||
| trainTask: '训练任务', | |||||
| codeBranch: '代码分支', | |||||
| bootFile: '启动文件', | |||||
| trainDataset: '训练数据集', | |||||
| specInfo: '规格', | |||||
| workServerNumber: '计算节点', | |||||
| runParameters: '运行参数', | |||||
| seeMore: '查看更多信息', | |||||
| collapseDetails: '折叠详细信息', | |||||
| modelFilesList: '模型文件列表', | |||||
| fileName: '文件名称', | |||||
| fileSize: '文件大小', | |||||
| updateTime: '更新时间', | |||||
| operate: '操作', | |||||
| delete: '删除', | |||||
| infoModificationFailed: '信息修改失败', | |||||
| deleteModelFileConfirmTips: '请确认是否删除当前模型文件?', | |||||
| modelFileDeleteFailed: '模型文件删除失败', | |||||
| }, | |||||
| }; | }; | ||||
| export default zh; | export default zh; | ||||
| @@ -33,11 +33,9 @@ | |||||
| drag | drag | ||||
| > | > | ||||
| <div class="el-upload__text"> | <div class="el-upload__text"> | ||||
| {{ $t("dragThePictureHere") | |||||
| }}<span style="color: rgba(136, 136, 136, 0.87)">{{ | |||||
| $t("or") | |||||
| }}</span | |||||
| >{{ $t("clickUpload") }} | |||||
| <span> | |||||
| <span>{{ $t("dragThePictureHere") }}</span><span style="color: rgba(136, 136, 136, 0.87)">{{ $t("or") }}</span><span>{{ $t("clickUpload") }}</span> | |||||
| </span> | |||||
| </div> | </div> | ||||
| </el-upload> | </el-upload> | ||||
| @@ -0,0 +1,706 @@ | |||||
| <template> | |||||
| <div> | |||||
| <div class="ui header"> | |||||
| <div class="ui breadcrumb"> | |||||
| <a class="section" :href="`${repo}/modelmanage/show_model`">{{ $t('modelManage.modelManage') }}</a> | |||||
| <div class="divider"> / </div> | |||||
| <div class="active section">{{ this.state.name }}</div> | |||||
| </div> | |||||
| <div class="version"> | |||||
| <el-select v-model="curVersion" @change="changeVersion" placeholder=""> | |||||
| <el-option v-for="item in modelList" :value="item.version" :key="item.version" :label="item.version"> | |||||
| </el-option> | |||||
| </el-select> | |||||
| </div> | |||||
| </div> | |||||
| <div class="content"> | |||||
| <div class="detail-info"> | |||||
| <div class="title">{{ $t('modelManage.basicInfo') }}:</div> | |||||
| <div class="area-c"> | |||||
| <div class="area"> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.useCluster') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" :title="state.typeStr"> | |||||
| {{ state.typeStr }} | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.modelSize') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" :title="state.modelSize">{{ state.modelSize }}</div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row" :class="isEidtDescr ? 'edit-row' : ''"> | |||||
| <div class="tit">{{ $t('modelManage.descr') }}:</div> | |||||
| <div class="val" :class="isEidtDescr ? 'edit-val' : ''"> | |||||
| <div v-if="!isEidtDescr" class="txt-wrap" :title="state.description" | |||||
| style="max-width:100%;width:unset;padding-right:20px;"> | |||||
| <span>{{ state.description }}</span> | |||||
| <i v-if="canOperate" style="position:absolute;right:0;top:3px;color:rgb(22, 132, 252);cursor:pointer;" | |||||
| class="el-icon-edit" @click="editDescr = state._description; isEidtDescr = true;"></i> | |||||
| </div> | |||||
| <div class="txt-edit" v-if="isEidtDescr"> | |||||
| <el-input type="textarea" v-model="editDescr" :maxLength="255" | |||||
| :placeholder="$t('modelManage.modelDescrInputTips')"></el-input> | |||||
| <i style="position:absolute;right:-4px;bottom:20px;color:rgb(255, 37, 37);cursor:pointer;" | |||||
| class="icon times" @click="isEidtDescr = false;"></i> | |||||
| <i style="position:absolute;right:-5px;bottom:2px;color:rgb(39, 177, 72);cursor:pointer;" | |||||
| @click="submitEidt('descr')" class="icon check"></i> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="area"> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.modelEngine') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" :title="state.engineName">{{ state.engineName }}</div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.createTime') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" :title="state.createTime">{{ state.createTime }}</div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row" :class="isEidtLabel ? 'edit-row' : ''"> | |||||
| <div class="tit">{{ $t('modelManage.label') }}:</div> | |||||
| <div class="val" :class="isEidtLabel ? 'edit-val' : ''"> | |||||
| <div v-if="!isEidtLabel" class="txt-wrap" :title="state.label" | |||||
| style="max-width:100%;width:unset;padding-right:20px;"> | |||||
| <span>{{ state.label }}</span> | |||||
| <i v-if="canOperate" style="position:absolute;right:0;top:3px;color:rgb(22, 132, 252);cursor:pointer;" | |||||
| class="el-icon-edit" @click="editLabel = state._label; isEidtLabel = true;"></i> | |||||
| </div> | |||||
| <div class="txt-edit" v-if="isEidtLabel"> | |||||
| <el-input v-model="editLabel" :maxLength="255" :placeholder="$t('modelManage.modelLabelInputTips')" | |||||
| @input="labelInput"></el-input> | |||||
| <i style="position:absolute;right:-5px;bottom:20px;color:rgb(255, 37, 37);cursor:pointer;" | |||||
| class="icon times" @click="isEidtLabel = false;"></i> | |||||
| <i style="position:absolute;right:-5px;bottom:2px;color:rgb(39, 177, 72);cursor:pointer;" | |||||
| @click="submitEidt('label')" class="icon check"></i> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div v-show="isExpanded" style="margin-top:8px;" class="title">{{ $t('modelManage.trainTaskInfo') }}:</div> | |||||
| <div v-show="isExpanded" class="area-c"> | |||||
| <div class="area"> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.trainTask') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" v-html="state.displayJobName"></div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.codeBranch') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" v-html="state.branchName"></div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.bootFile') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" :title="state.bootFile">{{ state.bootFile }}</div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.trainDataset') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" :title="state.datasetName">{{ state.datasetName }}</div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="area"> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.specInfo') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" :title="state.specStr">{{ state.specStr }}</div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.workServerNumber') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" :title="state.workServerNumber">{{ state.workServerNumber }}</div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row"> | |||||
| <div class="tit">{{ $t('modelManage.runParameters') }}:</div> | |||||
| <div class="val"> | |||||
| <div class="txt-wrap" :title="state.parameters">{{ state.parameters }}</div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="expand-line"> | |||||
| <div class="line"></div> | |||||
| <div class="expand-btn" @click="isExpanded = !isExpanded"> | |||||
| <i class="icon chevron circle down" :class="isExpanded ? 'up' : ''"></i> | |||||
| <span>{{ isExpanded ? $t('modelManage.collapseDetails') : $t('modelManage.seeMore') }}</span> | |||||
| </div> | |||||
| <div class="line"></div> | |||||
| </div> | |||||
| <div class="files-info"> | |||||
| <div class="top"> | |||||
| <div style="width:100%;margin-right:20px;"> | |||||
| <div class="title">{{ $t('modelManage.modelFilesList') }}:</div> | |||||
| <div class="title files-path-c" style="margin-top:8px;margin-bottom:4px"> | |||||
| <div class="file-path" v-for="(item, index) in filePath"> | |||||
| <span v-if="index == filePath.length - 1" class="path-name">{{ item.label }}</span> | |||||
| <a v-if="index != filePath.length - 1" class="path-name canback" @click="goBackDir(item)">{{ item.label | |||||
| }}</a> | |||||
| <span style="color:rgba(0,0,0,.4);" class="divider"> / </span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div> | |||||
| <el-button v-if="modelType == 1 && canOperate" type="primary" icon="el-icon-upload" @click="goUploadPage"> | |||||
| {{ $t('modelManage.uploadModelFiles') }} | |||||
| </el-button> | |||||
| </div> | |||||
| </div> | |||||
| <div class="table-container"> | |||||
| <el-table ref="tableRef" :data="filesList" row-key="sn" style="width: 100%" v-loading="loading" stripe> | |||||
| <el-table-column column-key="FileName" prop="FileName" sortable | |||||
| :sort-method="(a, b) => a.FileName.toLocaleLowerCase().localeCompare(b.FileName.toLocaleLowerCase())" | |||||
| :label="$t('modelManage.fileName')" align="left" header-align="left"> | |||||
| <template slot-scope="scope"> | |||||
| <div class="tbl-file-name"> | |||||
| <a v-if="scope.row.IsDir" @click="goNextDir(scope.row)" href="javascript:;"> | |||||
| <div class="fitted" :title="scope.row.FileName"> | |||||
| <i class="icon folder" width="16" height="16" aria-hidden="true"></i> | |||||
| <span>{{ scope.row.FileName }}</span> | |||||
| </div> | |||||
| </a> | |||||
| <a v-else :class="!canOperate ? 'disabled-download' : ''" | |||||
| :href="canOperate ? `${repo}/modelmanage/${state.id}/downloadsingle?parentDir=${filePath.length > 1 ? encodeURIComponent(filePath.map(item => item.path).join('/').slice(1) + '/') : ''}&fileName=${scope.row.FileName}` : 'javascript:;'"> | |||||
| <div class="fitted" :title="scope.row.FileName"> | |||||
| <i class="icon file" width="16" height="16" aria-hidden="true"></i> | |||||
| <span>{{ scope.row.FileName }}</span> | |||||
| </div> | |||||
| </a> | |||||
| </div> | |||||
| </template> | |||||
| </el-table-column> | |||||
| <el-table-column column-key="SizeShow" prop="SizeShow" sortable :sort-method="(a, b) => a.Size - b.Size" | |||||
| :label="$t('modelManage.fileSize')" align="center" header-align="center" width="200"> | |||||
| </el-table-column> | |||||
| <el-table-column column-key="ModTime" prop="ModTime" sortable | |||||
| :sort-method="(a, b) => a.ModTimeNum - b.ModTimeNum" :label="$t('modelManage.updateTime')" align="center" | |||||
| header-align="center" width="200"> | |||||
| </el-table-column> | |||||
| <el-table-column v-if="modelType == 1 && canDelete" column-key="operate" prop="operate" | |||||
| :label="$t('modelManage.operate')" align="center" header-align="center" width="200"> | |||||
| <template slot-scope="scope"> | |||||
| <span v-if="!scope.row.IsDir" class="btn-del" @click="deleteFile(scope.row)">{{ $t('modelManage.delete') | |||||
| }}</span> | |||||
| </template> | |||||
| </el-table-column> | |||||
| </el-table> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| import { getModelInfoByName, modifyModel, getModelFiles, deleteModelFile } from '~/apis/modules/modelmanage'; | |||||
| import { getUrlSearchParams, getListValueWithKey, transFileSize, renderSpecStr } from '~/utils'; | |||||
| import { MODEL_ENGINES } from '~/const'; | |||||
| import { formatDate } from 'element-ui/lib/utils/date-util'; | |||||
| const REPO_NAME = location.pathname.split('/')[2]; | |||||
| const MAX_LABEL_COUNT = 5; | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| modelType: '0', // 1-本地, 0-线上 | |||||
| canOperate: false, | |||||
| canDelete: false, | |||||
| isExpanded: false, | |||||
| loading: false, | |||||
| repo: location.pathname.split('/').slice(0, 3).join('/'), | |||||
| state: { | |||||
| type: 0, | |||||
| id: '', | |||||
| name: '', | |||||
| version: '0.0.1', | |||||
| engine: '0', | |||||
| label: '', | |||||
| description: '', | |||||
| }, | |||||
| editDescr: '', | |||||
| isEidtDescr: false, | |||||
| editLabel: '', | |||||
| isEidtLabel: false, | |||||
| engineList: MODEL_ENGINES, | |||||
| curVersion: '', | |||||
| modelList: [], | |||||
| filesList: [], | |||||
| filePath: [], | |||||
| }; | |||||
| }, | |||||
| components: {}, | |||||
| methods: { | |||||
| getDirFiles(dir) { | |||||
| dir = dir.length ? dir.slice(1) : ''; | |||||
| getModelFiles({ | |||||
| repo: this.repo, | |||||
| ID: this.state.id, | |||||
| parentDir: dir, | |||||
| }).then(res => { | |||||
| const list = res.data || []; | |||||
| list.forEach(item => { | |||||
| item.SizeShow = item.IsDir ? '' : transFileSize(item.Size); | |||||
| item.ModTimeNum = new Date(item.ModTime).getTime(); | |||||
| }) | |||||
| list.sort((a, b) => b.ModTimeNum - a.ModTimeNum); | |||||
| this.filesList = list; | |||||
| this.$refs['tableRef']?.clearSort(); | |||||
| }).catch(err => { | |||||
| console.log(err); | |||||
| }); | |||||
| }, | |||||
| goNextDir(item) { | |||||
| this.filePath.push({ | |||||
| label: item.FileName, | |||||
| path: item.FileName | |||||
| }); | |||||
| const dir = this.filePath.map((item) => item.path).join('/'); | |||||
| this.getDirFiles(dir); | |||||
| }, | |||||
| goBackDir(item) { | |||||
| const index = this.filePath.findIndex(pth => item === pth); | |||||
| this.filePath = this.filePath.slice(0, index + 1); | |||||
| const dir = this.filePath.map((item) => item.path).join('/'); | |||||
| this.getDirFiles(dir); | |||||
| }, | |||||
| changeVersion(version, noFileRefresh) { | |||||
| const data = this.modelList.filter((model) => model.version == version)[0]; | |||||
| this.modelType = data.modelType; | |||||
| this.canOperate = data.isCanOper; | |||||
| this.canDelete = data.isCanDelete; | |||||
| this.state.type = data.type; | |||||
| this.state.typeStr = data.type == 0 ? 'CPU/GPU' : data.type == 1 ? 'NPU' : ''; | |||||
| this.state.id = data.id; | |||||
| this.state.name = data.name; | |||||
| this.state.version = data.version; | |||||
| this.state.engine = data.engine.toString(); | |||||
| this.state.engineName = getListValueWithKey(MODEL_ENGINES, data.engine.toString()); | |||||
| this.state.modelSize = transFileSize(data.size); | |||||
| this.state.label = data.label || '--'; | |||||
| this.state._label = data.label; | |||||
| this.state.description = data.description || '--'; | |||||
| this.state._description = data.description; | |||||
| this.state.createTime = formatDate(new Date(data.createdUnix * 1000), 'yyyy-MM-dd HH:mm:ss'); | |||||
| const trainTaskInfo = data.trainTaskInfo ? JSON.parse(data.trainTaskInfo) : ''; | |||||
| Object.assign(this.state, { | |||||
| displayJobName: '--', | |||||
| branchName: '--', | |||||
| bootFile: '--', | |||||
| datasetName: '--', | |||||
| parameters: '--', | |||||
| workServerNumber: '--', | |||||
| specStr: '--', | |||||
| }); | |||||
| if (trainTaskInfo) { | |||||
| const parameters = trainTaskInfo.Parameters ? JSON.parse(trainTaskInfo.Parameters).parameter : []; | |||||
| const parametersStr = parameters.map((item) => { return item.label + '=' + item.value }).join('; '); | |||||
| const taskType = trainTaskInfo.Type; | |||||
| let taskUrl = location.href.split('modelmanage')[0]; | |||||
| if (taskType == 0) { | |||||
| taskUrl = taskUrl + 'cloudbrain/train-job/' + trainTaskInfo.JobID; | |||||
| } else if (taskType == 1) { | |||||
| taskUrl = taskUrl + 'modelarts/train-job/' + trainTaskInfo.JobID; | |||||
| } else if (taskType == 2) { | |||||
| taskUrl = taskUrl + 'grampus/train-job/' + trainTaskInfo.JobID; | |||||
| } | |||||
| const versionName = trainTaskInfo.VersionName; | |||||
| const versionHtml = versionName ? `<span class="append-txt" title="${versionName}">${versionName}</span>` : ''; | |||||
| const codeCommitID = data.codeCommitID; | |||||
| const codeCommitIDHtml = codeCommitID ? `<span class="append-txt" title="${codeCommitID}">${codeCommitID.slice(0, 10)}</span>` : ''; | |||||
| let specObj; | |||||
| try { | |||||
| specObj = trainTaskInfo.FlavorName ? JSON.parse(trainTaskInfo.FlavorName) : ''; | |||||
| } catch (e) { | |||||
| specObj = trainTaskInfo.FlavorName; | |||||
| } | |||||
| const sepcStr = typeof specObj == 'object' ? renderSpecStr(specObj, false) : specObj; | |||||
| Object.assign(this.state, { | |||||
| displayJobName: `<a href="${taskUrl}" title="${trainTaskInfo.DisplayJobName}">${trainTaskInfo.DisplayJobName}</a>${versionHtml}`, | |||||
| branchName: `<span>${trainTaskInfo.BranchName}</span>${codeCommitIDHtml}`, | |||||
| bootFile: trainTaskInfo.BootFile, | |||||
| datasetName: trainTaskInfo.DatasetName, | |||||
| parameters: parametersStr || '--', | |||||
| workServerNumber: trainTaskInfo.WorkServerNumber || '--', | |||||
| specStr: sepcStr || '--', | |||||
| }); | |||||
| } | |||||
| this.curVersion = version; | |||||
| if (!noFileRefresh) { | |||||
| this.filePath = [{ label: version, path: '' }]; | |||||
| this.getDirFiles('') | |||||
| } | |||||
| }, | |||||
| goUploadPage() { | |||||
| window.location.href = `${this.repo}/modelmanage/create_local_model_2?type=1&name=${encodeURIComponent(this.state.name)}&id=${this.state.id}`; | |||||
| }, | |||||
| backToModelListPage() { | |||||
| const list = window.location.href.split('/'); | |||||
| list.pop(); | |||||
| list.push('show_model'); | |||||
| window.location.href = list.join('/'); | |||||
| }, | |||||
| labelInput() { | |||||
| const hasEndSpace = this.editLabel[this.editLabel.length - 1] == ' '; | |||||
| const list = this.editLabel.trim().split(' ').filter(label => label != ''); | |||||
| this.editLabel = list.slice(0, MAX_LABEL_COUNT).join(' ') + (hasEndSpace && list.length < MAX_LABEL_COUNT ? ' ' : ''); | |||||
| }, | |||||
| submitEidt(type) { | |||||
| const obj = { | |||||
| repo: this.repo, | |||||
| type: this.state.type, | |||||
| id: this.state.id, | |||||
| name: this.state.name, | |||||
| version: this.state.version, | |||||
| engine: this.state.engine, | |||||
| label: type == 'label' ? this.editLabel : this.state.label, | |||||
| description: type == 'descr' ? this.editDescr : this.state.description, | |||||
| }; | |||||
| modifyModel(obj).then(res => { | |||||
| res = res.data; | |||||
| if (res && res.code == '0') { | |||||
| if (type == 'label') { | |||||
| this.state.label = this.editLabel; | |||||
| this.state._label = this.editLabel; | |||||
| this.isEidtLabel = false; | |||||
| } else if (type == 'descr') { | |||||
| this.state.description = this.editDescr; | |||||
| this.state._description = this.editDescr; | |||||
| this.isEidtDescr = false; | |||||
| } | |||||
| } else { | |||||
| this.$message({ | |||||
| type: 'error', | |||||
| message: this.$t('modelManage.infoModificationFailed'), | |||||
| }); | |||||
| } | |||||
| }).catch(err => { | |||||
| console.log(err); | |||||
| this.$message({ | |||||
| type: 'error', | |||||
| message: this.$t('modelManage.infoModificationFailed'), | |||||
| }); | |||||
| }); | |||||
| }, | |||||
| deleteFile(file) { | |||||
| this.$confirm(this.$t('modelManage.deleteModelFileConfirmTips'), this.$t('tips'), { | |||||
| confirmButtonText: this.$t('confirm1'), | |||||
| cancelButtonText: this.$t('cancel'), | |||||
| type: 'warning', | |||||
| lockScroll: false, | |||||
| }).then(() => { | |||||
| this.loading = true; | |||||
| deleteModelFile({ | |||||
| repo: this.repo, | |||||
| id: this.state.id, | |||||
| fileName: file.FileName, | |||||
| }).then(res => { | |||||
| res = res.data; | |||||
| if (res.code == '0') { | |||||
| setTimeout(() => { | |||||
| this.loading = false; | |||||
| this.updateModelInfo(); | |||||
| const dir = this.filePath.map((item) => item.path).join('/'); | |||||
| this.getDirFiles(dir); | |||||
| }, 30); | |||||
| } else { | |||||
| this.loading = false; | |||||
| this.$message({ | |||||
| type: 'error', | |||||
| message: this.$t('modelManage.modelFileDeleteFailed'), | |||||
| }); | |||||
| } | |||||
| }).catch(err => { | |||||
| console.log(err); | |||||
| this.$message({ | |||||
| type: 'error', | |||||
| message: this.$t('modelManage.modelFileDeleteFailed'), | |||||
| }); | |||||
| }); | |||||
| }).catch(() => { }); | |||||
| }, | |||||
| updateModelInfo() { | |||||
| getModelInfoByName({ | |||||
| repo: this.repo, | |||||
| name: this.state.name, | |||||
| }).then(res => { | |||||
| const list = res.data || []; | |||||
| this.modelList = list; | |||||
| const noFileRefresh = true; | |||||
| this.changeVersion(this.curVersion, noFileRefresh); | |||||
| }).catch(err => { | |||||
| console.log(err); | |||||
| }); | |||||
| }, | |||||
| }, | |||||
| mounted() { | |||||
| const urlParams = getUrlSearchParams(); | |||||
| if (urlParams.name) { | |||||
| this.state.name = urlParams.name; | |||||
| this.loading = true; | |||||
| getModelInfoByName({ | |||||
| repo: this.repo, | |||||
| name: urlParams.name, | |||||
| }).then(res => { | |||||
| this.loading = false; | |||||
| const list = res.data || []; | |||||
| this.modelList = list; | |||||
| if (list && list.length) { | |||||
| const data = list[0]; | |||||
| this.changeVersion(data.version); | |||||
| } | |||||
| }).catch(err => { | |||||
| this.loading = false; | |||||
| console.log(err); | |||||
| this.backToModelListPage(); | |||||
| }); | |||||
| } else { | |||||
| this.backToModelListPage(); | |||||
| } | |||||
| }, | |||||
| beforeDestroy() { | |||||
| }, | |||||
| }; | |||||
| </script> | |||||
| <style scoped lang="less"> | |||||
| .header { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| .version { | |||||
| margin-left: 16px; | |||||
| width: 90px; | |||||
| } | |||||
| } | |||||
| .content { | |||||
| .title { | |||||
| font-weight: 550; | |||||
| font-size: 14px; | |||||
| color: rgb(16, 16, 16); | |||||
| margin-bottom: 10px; | |||||
| } | |||||
| .detail-info { | |||||
| border: 1px solid rgb(232, 232, 232); | |||||
| border-bottom: none; | |||||
| padding: 22px; | |||||
| padding-bottom: 1px; | |||||
| .area-c { | |||||
| display: flex; | |||||
| .area { | |||||
| flex: 1; | |||||
| .row { | |||||
| display: flex; | |||||
| height: 32px; | |||||
| margin-bottom: 4px; | |||||
| align-items: center; | |||||
| &.edit-row { | |||||
| height: unset; | |||||
| } | |||||
| .tit { | |||||
| width: 160px; | |||||
| text-align: right; | |||||
| color: rgb(136, 136, 136); | |||||
| } | |||||
| .val { | |||||
| flex: 1; | |||||
| color: rgb(16, 16, 16); | |||||
| position: relative; | |||||
| height: 20px; | |||||
| &.edit-val { | |||||
| height: unset; | |||||
| } | |||||
| .txt-wrap { | |||||
| position: absolute; | |||||
| overflow: hidden; | |||||
| text-overflow: ellipsis; | |||||
| white-space: nowrap; | |||||
| width: 100%; | |||||
| /deep/.append-txt { | |||||
| margin-left: 6px; | |||||
| background-color: gainsboro; | |||||
| padding: 2px; | |||||
| border-radius: 2px; | |||||
| font-size: 12px; | |||||
| } | |||||
| } | |||||
| } | |||||
| .txt-edit { | |||||
| padding-right: 20px; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .expand-line { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| border: 1px solid rgb(232, 232, 232); | |||||
| border-top: none; | |||||
| border-bottom: none; | |||||
| padding: 16px 0; | |||||
| .line { | |||||
| flex: 1; | |||||
| height: 1px; | |||||
| background-color: rgb(232, 232, 232); | |||||
| margin: 0 22px; | |||||
| } | |||||
| .expand-btn { | |||||
| color: rgba(22, 132, 252, 1); | |||||
| cursor: pointer; | |||||
| .icon { | |||||
| margin-right: 2px; | |||||
| font-size: 14px; | |||||
| color: rgba(22, 132, 252, 0.8), | |||||
| } | |||||
| } | |||||
| } | |||||
| .files-info { | |||||
| border: 1px solid rgb(232, 232, 232); | |||||
| border-top: none; | |||||
| border-bottom: none; | |||||
| .top { | |||||
| padding: 0 22px 8px 22px; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: space-between; | |||||
| } | |||||
| .files-path-c { | |||||
| margin-bottom: 4px; | |||||
| height: 20px; | |||||
| .file-path { | |||||
| margin-right: 6px; | |||||
| float: left; | |||||
| .path-name { | |||||
| &.canback { | |||||
| color: #4183c4; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .table-container { | |||||
| /deep/ .el-table__header { | |||||
| th { | |||||
| background: rgb(245, 245, 246); | |||||
| color: rgb(16, 16, 16); | |||||
| font-weight: 400; | |||||
| font-size: 14px; | |||||
| } | |||||
| } | |||||
| /deep/ .el-table__body { | |||||
| td { | |||||
| color: rgb(16, 16, 16); | |||||
| font-weight: 400; | |||||
| font-size: 14px; | |||||
| } | |||||
| } | |||||
| .tbl-file-name { | |||||
| height: 32px; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| overflow: hidden; | |||||
| font-size: 16px; | |||||
| font-weight: 500; | |||||
| position: relative; | |||||
| a { | |||||
| max-width: 100%; | |||||
| .fitted { | |||||
| overflow: hidden; | |||||
| text-overflow: ellipsis; | |||||
| white-space: nowrap; | |||||
| max-width: 100%; | |||||
| } | |||||
| } | |||||
| .disabled-download { | |||||
| cursor: default; | |||||
| pointer-events: none; | |||||
| color: rgba(0, 0, 0, .6) !important; | |||||
| opacity: .45 !important; | |||||
| } | |||||
| } | |||||
| .btn-del { | |||||
| color: #0366d6; | |||||
| cursor: pointer; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .el-select-dropdown__item.selected { | |||||
| color: rgba(0, 0, 0, .95); | |||||
| } | |||||
| /deep/ .el-select { | |||||
| .is-focus { | |||||
| .el-input__inner { | |||||
| border-color: #85b7d9; | |||||
| } | |||||
| } | |||||
| } | |||||
| .el-select { | |||||
| /deep/ .el-input__inner { | |||||
| font-weight: 600; | |||||
| } | |||||
| } | |||||
| /deep/ .el-input__inner { | |||||
| &:focus { | |||||
| border-color: #85b7d9; | |||||
| } | |||||
| } | |||||
| /deep/ .el-textarea__inner { | |||||
| &:focus { | |||||
| border-color: #85b7d9; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @@ -0,0 +1,17 @@ | |||||
| import Vue from 'vue'; | |||||
| import ElementUI from 'element-ui'; | |||||
| import 'element-ui/lib/theme-chalk/index.css'; | |||||
| import localeEn from 'element-ui/lib/locale/lang/en'; | |||||
| import localeZh from 'element-ui/lib/locale/lang/zh-CN'; | |||||
| import { i18n, lang } from '~/langs'; | |||||
| import App from './modelmanage-common-detail.vue'; | |||||
| Vue.use(ElementUI, { | |||||
| locale: lang === 'zh-CN' ? localeZh : localeEn, | |||||
| size: 'small', | |||||
| }); | |||||
| new Vue({ | |||||
| i18n, | |||||
| render: (h) => h(App), | |||||
| }).$mount('#__vue-root'); | |||||
| @@ -0,0 +1,470 @@ | |||||
| <template> | |||||
| <div> | |||||
| <div class="header"> | |||||
| <span class="title">{{ type == '1' ? $t('modelManage.modifyModelInfo') : $t('modelManage.importLocalModel') | |||||
| }}</span> | |||||
| </div> | |||||
| <div class="content"> | |||||
| <div class="guide-c" v-if="type != '1'"> | |||||
| <div class="step focused"> | |||||
| <div class="num">1</div> | |||||
| <div class="txt">{{ $t('modelManage.createModel') }}</div> | |||||
| </div> | |||||
| <div class="line"></div> | |||||
| <div class="step"> | |||||
| <div class="num">2</div> | |||||
| <div class="txt">{{ $t('modelManage.uploadModelFiles') }}</div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row-c" v-loading="loading"> | |||||
| <div class="row"> | |||||
| <div class="r-title"><label class="required">{{ $t('modelManage.useCluster') }}</label></div> | |||||
| <div class="r-content" style="display:flex;"> | |||||
| <div class="cluster-type-btn" v-if="type != 1 || type == 1 && state.type === 0" | |||||
| :class="state.type === 0 ? 'focused' : ''" | |||||
| :style="type != 1 ? 'border-top-right-radius:unset;border-bottom-right-radius:unset;' : ''" | |||||
| @click="state.type = 0; state.engine = '0'"> | |||||
| <svg xmlns="http://www.w3.org/2000/svg" | |||||
| class="icon styles__StyledSVGIconPathComponent-sc-16fsqc8-0 cSaWDI svg-icon-path-icon fill" | |||||
| viewBox="0 0 32 32" width="16" height="16"> | |||||
| <defs data-reactroot=""></defs> | |||||
| <g> | |||||
| <path | |||||
| d="M4 3.989c0-0.731 0.593-1.323 1.324-1.323h21.352c0.729 0.005 1.318 0.594 1.324 1.322v24.022c-0.001 0.731-0.593 1.323-1.324 1.323h-21.352c-0.729-0.005-1.318-0.594-1.324-1.322v-24.022zM25.333 14.667v-9.333h-18.667v9.333h18.667zM25.333 17.333h-18.667v9.333h18.667v-9.333zM12 8h8v2.667h-8v-2.667zM12 20h8v2.667h-8v-2.667z"> | |||||
| </path> | |||||
| </g> | |||||
| </svg> | |||||
| <span class="txt">CPU / GPU</span> | |||||
| </div> | |||||
| <div class="cluster-type-btn" v-if="type != 1 || type == 1 && state.type === 1" | |||||
| :class="state.type === 1 ? 'focused' : ''" | |||||
| :style="type != 1 ? 'border-top-left-radius:unset;border-bottom-left-radius:unset;' : ''" | |||||
| @click="state.type = 1; state.engine = '2'"> | |||||
| <svg xmlns="http://www.w3.org/2000/svg" | |||||
| class="icon styles__StyledSVGIconPathComponent-sc-16fsqc8-0 iKfgJk svg-icon-path-icon fill" | |||||
| viewBox="0 0 32 32" width="16" height="16"> | |||||
| <defs data-reactroot=""></defs> | |||||
| <g> | |||||
| <path | |||||
| d="M4 3.989c0-0.731 0.593-1.323 1.324-1.323h21.352c0.729 0.005 1.318 0.594 1.324 1.322v24.022c-0.001 0.731-0.593 1.323-1.324 1.323h-21.352c-0.729-0.005-1.318-0.594-1.324-1.322v-24.022zM25.333 14.667v-9.333h-18.667v9.333h18.667zM25.333 17.333h-18.667v9.333h18.667v-9.333zM12 8h8v2.667h-8v-2.667zM12 20h8v2.667h-8v-2.667z"> | |||||
| </path> | |||||
| </g> | |||||
| </svg> | |||||
| <span class="txt">Ascend NPU</span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row" :class="nameErr ? 'error' : ''"> | |||||
| <div class="r-title"><label class="required">{{ $t('modelManage.modelName') }}</label></div> | |||||
| <div class="r-content"> | |||||
| <el-input size="medium" :maxLength="25" v-model="state.name" @blur="checkName" | |||||
| :placeholder="$t('modelManage.pleaseInputModelName')"> | |||||
| </el-input> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row" v-show="isShowVersion"> | |||||
| <div class="r-title"><label class="required">{{ $t('modelManage.version') }}</label></div> | |||||
| <div class="r-content"> | |||||
| <el-input class="input-disabled" style="width:288px;" size="medium" v-model="state.version" readonly> | |||||
| </el-input> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row"> | |||||
| <div class="r-title"><label class="required">{{ $t('modelManage.modelEngine') }}</label></div> | |||||
| <div class="r-content"> | |||||
| <el-select style="width:288px;" size="medium" v-model="state.engine" placeholder=""> | |||||
| <el-option v-for="item in engineList" :key="item.k" :label="item.v" :value="item.k"> | |||||
| </el-option> | |||||
| </el-select> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row"> | |||||
| <div class="r-title"><label>{{ $t('modelManage.modelLabel') }}</label></div> | |||||
| <div class="r-content"> | |||||
| <el-input size="medium" :maxLength="255" v-model="state.label" | |||||
| :placeholder="$t('modelManage.modelLabelInputTips')" @input="labelInput"></el-input> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row" style="align-items:flex-start;"> | |||||
| <div class="r-title"><label>{{ $t('modelManage.modelDescr') }}</label></div> | |||||
| <div class="r-content"> | |||||
| <el-input type="textarea" :maxLength="255" size="medium" v-model="state.description" :rows="3" | |||||
| :placeholder="$t('modelManage.modelDescrInputTips')"> | |||||
| </el-input> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row" style="margin-top:20px"> | |||||
| <div class="r-title"><label></label></div> | |||||
| <div class="r-content"> | |||||
| <el-button size="medium" class="green" @click="submit">{{ type == '1' ? $t('modelManage.confirm') : | |||||
| $t('modelManage.createModel') | |||||
| }} | |||||
| </el-button> | |||||
| <el-button size="medium" @click="cancel">{{ $t('modelManage.cancel') }}</el-button> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| import { saveLocalModel, getModelInfoByName, modifyModel } from '~/apis/modules/modelmanage'; | |||||
| import { getUrlSearchParams } from '~/utils'; | |||||
| import { MODEL_ENGINES } from '~/const' | |||||
| const REPO_NAME = location.pathname.split('/')[2]; | |||||
| const MAX_LABEL_COUNT = 5; | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| type: '0', // 1-修改,其它-新增 | |||||
| loading: false, | |||||
| state: { | |||||
| type: 0, | |||||
| name: REPO_NAME + '_model_' + Math.random().toString(36).substr(2, 4), | |||||
| version: '0.0.1', | |||||
| engine: '0', | |||||
| label: '', | |||||
| description: '', | |||||
| }, | |||||
| nameErr: false, | |||||
| isShowVersion: false, | |||||
| engineList: MODEL_ENGINES, | |||||
| }; | |||||
| }, | |||||
| components: {}, | |||||
| methods: { | |||||
| checkName() { | |||||
| this.nameErr = !this.state.name; | |||||
| return !this.nameErr; | |||||
| }, | |||||
| labelInput() { | |||||
| const hasEndSpace = this.state.label[this.state.label.length - 1] == ' '; | |||||
| const list = this.state.label.trim().split(' ').filter(label => label != ''); | |||||
| this.state.label = list.slice(0, MAX_LABEL_COUNT).join(' ') + (hasEndSpace && list.length < MAX_LABEL_COUNT ? ' ' : ''); | |||||
| }, | |||||
| submit() { | |||||
| if (!this.checkName()) { | |||||
| // this.$message({ | |||||
| // type: 'info', | |||||
| // message: this.$t('modelManage.pleaseInputModelName'), | |||||
| // }); | |||||
| return; | |||||
| } | |||||
| const submintApi = this.type == '1' ? modifyModel : saveLocalModel; | |||||
| submintApi({ | |||||
| repo: location.pathname.split('/').slice(0, 3).join('/'), | |||||
| ...this.state, | |||||
| }).then(res => { | |||||
| res = res.data; | |||||
| if (res && res.code == '0') { | |||||
| if (this.type == '1') { | |||||
| this.goDetail(); | |||||
| return; | |||||
| } | |||||
| const list = window.location.href.split('/'); | |||||
| list.pop(); | |||||
| list.push('create_local_model_2'); | |||||
| window.location.href = list.join('/') + '?type=0&name=' + encodeURIComponent(this.state.name) + '&id=' + res.id; | |||||
| } else if (res && res.code == '-1') { | |||||
| this.$message({ | |||||
| type: 'error', | |||||
| message: res.msg, | |||||
| }); | |||||
| } else { | |||||
| this.$message({ | |||||
| type: 'error', | |||||
| message: this.type == '1' ? this.$t('modelManage.modelModifyFailed') : this.$t('modelManage.modelCreateFailed'), | |||||
| }); | |||||
| } | |||||
| }).catch(err => { | |||||
| console.log(err); | |||||
| }); | |||||
| }, | |||||
| cancel() { | |||||
| const list = window.location.href.split('/'); | |||||
| list.pop(); | |||||
| list.push('show_model'); | |||||
| window.location.href = list.join('/'); | |||||
| }, | |||||
| goDetail() { | |||||
| const list = window.location.href.split('/'); | |||||
| list.pop(); | |||||
| list.push('show_model_info'); | |||||
| window.location.href = list.join('/') + '?name=' + encodeURIComponent(this.state.name); | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| const urlParams = getUrlSearchParams(); | |||||
| if (urlParams.type == '1' && urlParams.name && urlParams.id) { // update | |||||
| this.type = urlParams.type; | |||||
| this.state.name = urlParams.name; | |||||
| this.state.id = urlParams.id; | |||||
| this.loading = true; | |||||
| getModelInfoByName({ | |||||
| repo: location.pathname.split('/').slice(0, 3).join('/'), | |||||
| name: urlParams.name, | |||||
| id: urlParams.id | |||||
| }).then(res => { | |||||
| this.loading = false; | |||||
| const list = res.data; | |||||
| if (list && list.length) { | |||||
| const data = list[0]; | |||||
| this.state.type = data.type; | |||||
| this.state.id = data.id; | |||||
| this.state.name = data.name; | |||||
| this.state.version = data.version; | |||||
| this.state.engine = data.engine.toString(); | |||||
| this.state.label = data.label; | |||||
| this.state.description = data.description; | |||||
| } | |||||
| }).catch(err => { | |||||
| this.loading = false; | |||||
| console.log(err); | |||||
| this.cancel(); | |||||
| }); | |||||
| } | |||||
| }, | |||||
| beforeDestroy() { | |||||
| }, | |||||
| }; | |||||
| </script> | |||||
| <style scoped lang="less"> | |||||
| .header { | |||||
| height: 45px; | |||||
| border-color: rgb(212, 212, 213); | |||||
| border-width: 1px; | |||||
| border-style: solid; | |||||
| border-radius: 5px 5px 0px 0px; | |||||
| font-size: 14px; | |||||
| background: rgb(240, 240, 240); | |||||
| display: flex; | |||||
| align-items: center; | |||||
| .title { | |||||
| font-weight: 600; | |||||
| font-size: 16px; | |||||
| color: rgb(16, 16, 16); | |||||
| margin-left: 10px; | |||||
| } | |||||
| } | |||||
| .content { | |||||
| margin-top: -1px; | |||||
| border-color: rgb(212, 212, 213); | |||||
| border-width: 1px; | |||||
| border-style: solid; | |||||
| padding: 30px 0; | |||||
| border-top: none; | |||||
| .guide-c { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| margin-bottom: 20px; | |||||
| .step { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| color: rgb(136, 136, 136); | |||||
| .num { | |||||
| border: 1px solid rgb(136, 136, 136); | |||||
| width: 34px; | |||||
| height: 34px; | |||||
| font-size: 24px; | |||||
| text-align: center; | |||||
| line-height: 34px; | |||||
| border-radius: 17px; | |||||
| margin-right: 8px; | |||||
| } | |||||
| .txt { | |||||
| font-weight: 600; | |||||
| } | |||||
| &.focused { | |||||
| color: rgb(22, 132, 252); | |||||
| .num { | |||||
| border-color: rgb(22, 132, 252); | |||||
| } | |||||
| } | |||||
| } | |||||
| .line { | |||||
| height: 2px; | |||||
| width: 50px; | |||||
| background-color: rgb(187, 187, 187); | |||||
| margin: 0 10px; | |||||
| } | |||||
| } | |||||
| .row-c { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| flex-direction: column; | |||||
| margin: 0 auto; | |||||
| width: 80%; | |||||
| .row { | |||||
| width: 100%; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| margin: 8px 0; | |||||
| margin-left: -190px; | |||||
| .r-title { | |||||
| text-align: right; | |||||
| font-size: .92857143em; | |||||
| font-weight: 700; | |||||
| color: rgba(0, 0, 0, .87); | |||||
| width: 200px; | |||||
| margin-right: 28px; | |||||
| position: relative; | |||||
| .required { | |||||
| &::after { | |||||
| position: absolute; | |||||
| margin: -0.2em 0 0 0.2em; | |||||
| content: '*'; | |||||
| color: #db2828; | |||||
| } | |||||
| } | |||||
| } | |||||
| &.error { | |||||
| .r-title { | |||||
| color: #9f3a38; | |||||
| } | |||||
| .r-content { | |||||
| /deep/.el-input__inner { | |||||
| color: #9f3a38; | |||||
| background: #fff6f6; | |||||
| border-color: #e0b4b4; | |||||
| &::placeholder { | |||||
| color: #e0b4b4; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .r-content { | |||||
| flex: 1; | |||||
| .cluster-type-btn { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| border: 1px solid #DCDFE6; | |||||
| height: 36px; | |||||
| padding: 10px; | |||||
| cursor: pointer; | |||||
| border-radius: 4px; | |||||
| .icon { | |||||
| margin-right: 5px; | |||||
| } | |||||
| &.focused { | |||||
| border-color: rgb(50, 145, 248); | |||||
| color: rgb(50, 145, 248); | |||||
| cursor: default; | |||||
| .icon { | |||||
| :not([stroke]) { | |||||
| fill: rgb(50, 145, 248); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .input-disabled { | |||||
| /deep/ .el-input__inner { | |||||
| background-color: #f5f5f6 !important; | |||||
| color: #888888 !important; | |||||
| } | |||||
| } | |||||
| .el-select-dropdown__item.selected { | |||||
| color: rgba(0, 0, 0, .95); | |||||
| } | |||||
| /deep/ .el-button { | |||||
| background-color: #e0e1e2; | |||||
| color: rgba(0, 0, 0, .6); | |||||
| border-color: transparent; | |||||
| transition: opacity .1s ease, background-color .1s ease, color .1s ease, box-shadow .1s ease, background .1s ease, -webkit-box-shadow .1s ease; | |||||
| will-change: auto; | |||||
| -webkit-tap-highlight-color: transparent; | |||||
| &:hover { | |||||
| border-color: transparent; | |||||
| background-color: #cacbcd; | |||||
| color: rgba(0, 0, 0, .8); | |||||
| } | |||||
| &:focus { | |||||
| background-color: #cacbcd; | |||||
| color: rgba(0, 0, 0, .8); | |||||
| border-color: transparent; | |||||
| } | |||||
| &:active { | |||||
| background-color: #babbbc; | |||||
| color: rgba(0, 0, 0, .9); | |||||
| border-color: transparent; | |||||
| } | |||||
| &.green { | |||||
| background-color: #5bb973; | |||||
| color: #fff; | |||||
| &:hover { | |||||
| background-color: #16ab39; | |||||
| border-color: transparent; | |||||
| } | |||||
| &:focus { | |||||
| background-color: #0ea432; | |||||
| border-color: transparent; | |||||
| } | |||||
| &:active { | |||||
| background-color: #198f35; | |||||
| border-color: transparent; | |||||
| } | |||||
| } | |||||
| } | |||||
| /deep/ .el-select { | |||||
| .is-focus { | |||||
| .el-input__inner { | |||||
| border-color: #85b7d9; | |||||
| } | |||||
| } | |||||
| } | |||||
| /deep/ .el-input__inner { | |||||
| &:focus { | |||||
| border-color: #85b7d9; | |||||
| } | |||||
| } | |||||
| /deep/ .el-textarea__inner { | |||||
| &:focus { | |||||
| border-color: #85b7d9; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @@ -0,0 +1,851 @@ | |||||
| <template> | |||||
| <div> | |||||
| <div class="header"> | |||||
| <span class="title">{{ type == '1' ? $t('modelManage.addModelFiles') : $t('modelManage.uploadModelFiles') | |||||
| }}</span> | |||||
| </div> | |||||
| <div class="content ui form"> | |||||
| <div class="guide-c" v-if="type != '1'"> | |||||
| <div class="step"> | |||||
| <div class="num">1</div> | |||||
| <div class="txt">{{ $t('modelManage.createModel') }}</div> | |||||
| </div> | |||||
| <div class="line"></div> | |||||
| <div class="step focused"> | |||||
| <div class="num">2</div> | |||||
| <div class="txt">{{ $t('modelManage.uploadModelFiles') }}</div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row-c"> | |||||
| <div class="row"> | |||||
| <div class="r-title"><label class="required">{{ $t('modelManage.modelName') }}</label></div> | |||||
| <div class="r-content"> | |||||
| <el-input size="medium" class="input-disabled" v-model="state.name" | |||||
| :placeholder="$t('modelManage.pleaseInputModelName')" readonly> | |||||
| </el-input> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row" style="align-items:flex-start;"> | |||||
| <div class="r-title"><label class="required">{{ $t('modelManage.fileUpload') }}</label></div> | |||||
| <div class="r-content"> | |||||
| <div style="position:relative"> | |||||
| <form class="dropzone" ref="dropzoneRef"> | |||||
| <div class="dropzon-err-tips ui red message" v-show="showUploadErr" style="display:none;margin:2.5rem"> | |||||
| {{ uploadErrTxt }}</div> | |||||
| </form> | |||||
| <div class="not-allowed-placeholder" v-show="uploading"></div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row" style="margin-top:10px"> | |||||
| <div class="r-title"><label></label></div> | |||||
| <div class="r-content"> | |||||
| <el-button size="medium" class="green" @click="submit" :disabled="uploading">{{ $t('modelManage.upload') }} | |||||
| </el-button> | |||||
| <el-button size="medium" @click="cancel">{{ $t('modelManage.cancel') }}</el-button> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row" style="align-items:flex-start;"> | |||||
| <div class="r-title"><label>{{ $t('modelManage.uploadStatus') }}:</label></div> | |||||
| <div class="r-content"> | |||||
| <div v-for="(item, index) in uploadFiles" :key="item.upload.uuid" class="datast-upload-progress"> | |||||
| <span class="dataset-name nowrap" :title="item.name">{{ item.name }}</span> | |||||
| <div class="dataset-progress"> | |||||
| <el-progress :text-inside="true" :stroke-width="14" :percentage="uploadStatusList[index].progress"> | |||||
| </el-progress> | |||||
| </div> | |||||
| <div class="dataset-status nowrap"> | |||||
| <div class="status-flex"> | |||||
| <i v-if="uploadStatusList[index].infoCode === 1 || uploadStatusList[index].infoCode === 2" | |||||
| class="ri-close-circle-line failed"></i> | |||||
| <i v-if="uploadStatusList[index].infoCode === 0" class="ri-checkbox-circle-line success"></i> | |||||
| <span>{{ uploadStatusList[index].status }}</span> | |||||
| <el-tooltip v-if="uploadStatusList[index].infoCode === 1" class="item" effect="dark" placement="top"> | |||||
| <div slot="content"> {{ uploadStatusList[index].failedInfo }} </div> | |||||
| <i style="font-size: 16px; margin-left: 0.5rem; cursor: pointer" class="ri-question-fill"></i> | |||||
| </el-tooltip> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| import 'dropzone/dist/dropzone.css'; | |||||
| import Dropzone from 'dropzone'; | |||||
| import SparkMD5 from "spark-md5"; | |||||
| import { getModelInfoByName, getChunks, getNewMultipart, getMultipartUrl, setCompleteMultipart } from '~/apis/modules/modelmanage'; | |||||
| import { getUrlSearchParams } from '~/utils'; | |||||
| Dropzone.autoDiscover = false; | |||||
| const uploadChunkSize = 1024 * 1024 * 64; | |||||
| const md5ChunkSize = 1024 * 1024 * 64; | |||||
| const maxFileSize = 10; | |||||
| const maxModelFilesSize = window.MAX_MODEL_SIZE || 200 * 1024 * 1024 * 1024; // 200 GB | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| dropzoneHandler: null, | |||||
| type: '0', // 1-修改,其它-新增 | |||||
| state: { | |||||
| type: '', | |||||
| id: '', | |||||
| name: '', | |||||
| version: '', | |||||
| engine: '', | |||||
| label: '', | |||||
| description: '', | |||||
| size: 0, | |||||
| }, | |||||
| originData: null, | |||||
| showUploadErr: false, | |||||
| uploadErrTxt: '', | |||||
| uploadFiles: [], | |||||
| uploadLength: 0, | |||||
| uploadSuccessLength: 0, | |||||
| uploadStatusList: [], | |||||
| uploading: false, | |||||
| }; | |||||
| }, | |||||
| components: {}, | |||||
| methods: { | |||||
| initModelData() { | |||||
| const urlParams = getUrlSearchParams(); | |||||
| if (urlParams.name && urlParams.id) { | |||||
| this.type = urlParams.type || '0'; | |||||
| this.state.name = urlParams.name; | |||||
| this.state.id = urlParams.id; | |||||
| this.loading = true; | |||||
| getModelInfoByName({ | |||||
| repo: location.pathname.split('/').slice(0, 3).join('/'), | |||||
| name: urlParams.name, | |||||
| id: urlParams.id | |||||
| }).then(res => { | |||||
| this.loading = false; | |||||
| const list = res.data; | |||||
| if (list && list.length) { | |||||
| const data = list[0]; | |||||
| this.state.type = data.type; | |||||
| this.state.id = data.id; | |||||
| this.state.name = data.name; | |||||
| this.state.version = data.version; | |||||
| this.state.engine = data.engine.toString(); | |||||
| this.state.label = data.label; | |||||
| this.state.description = data.description; | |||||
| this.state.size = data.size || 0; | |||||
| this.originData = data; | |||||
| } else { | |||||
| this.cancel(); | |||||
| } | |||||
| }).catch(err => { | |||||
| this.loading = false; | |||||
| console.log(err); | |||||
| this.cancel(); | |||||
| }); | |||||
| } else { | |||||
| this.cancel(); | |||||
| } | |||||
| }, | |||||
| initDropZone() { | |||||
| this.dropzoneHandler = new Dropzone(this.$refs.dropzoneRef, { | |||||
| url: '/', | |||||
| maxFiles: 10, | |||||
| parallelUploads: 20, | |||||
| uploadMultiple: true, | |||||
| maxFilesize: maxModelFilesSize, | |||||
| timeout: 0, | |||||
| addRemoveLinks: true, | |||||
| autoProcessQueue: false, | |||||
| dictDefaultMessage: this.$t('modelManage.modelFileUploadDefaultTips'), | |||||
| dictFileTooBig: this.$t('modelManage.fileIstoBig'), | |||||
| dictRemoveFile: this.$t('modelManage.removeFile'), | |||||
| dictMaxFilesExceeded: this.getDefaultErrTxt(), | |||||
| }); | |||||
| this.dropzoneHandler.on("addedfile", file => { | |||||
| this.checkFiles(file); | |||||
| }); | |||||
| this.dropzoneHandler.on("removedfile", file => { | |||||
| this.checkFiles(); | |||||
| }); | |||||
| }, | |||||
| getDefaultErrTxt() { | |||||
| return this.$t('modelManage.modelFileUploadErrTips', { size: (maxModelFilesSize / (1024 * 1024 * 1024)).toFixed(2) }); | |||||
| }, | |||||
| showUploadErrInfo(state, info) { | |||||
| if (state) { | |||||
| this.uploadErrTxt = info; | |||||
| this.showUploadErr = true; | |||||
| } else { | |||||
| this.uploadErrTxt = ''; | |||||
| this.showUploadErr = false; | |||||
| } | |||||
| }, | |||||
| checkFiles(file, countStay) { | |||||
| const fileList = this.dropzoneHandler.getAcceptedFiles(); | |||||
| const filesSize = fileList.reduce((acc, item, index) => acc + item.size, 0) + (file && !countStay ? file.size : 0); | |||||
| const filesCount = fileList.length + (file && !countStay ? 1 : 0); | |||||
| const allfilesSize = filesSize + this.state.size; | |||||
| if (file && filesCount > maxFileSize) { | |||||
| this.dropzoneHandler.removeFile(file); | |||||
| this.showUploadErrInfo(true, this.getDefaultErrTxt()); | |||||
| return false; | |||||
| } | |||||
| if (filesCount > maxFileSize || allfilesSize > maxModelFilesSize) { | |||||
| this.showUploadErrInfo(true, this.getDefaultErrTxt()); | |||||
| return false; | |||||
| } | |||||
| if (file && file.name.length > 128) { | |||||
| this.showUploadErrInfo(true, this.$t('modelManage.modelFileNameTips')); | |||||
| this.uploadError(file, this.$t('modelManage.modelFileNameTips')); | |||||
| return false; | |||||
| } | |||||
| this.showUploadErrInfo(false); | |||||
| return true; | |||||
| }, | |||||
| resetFileStatus() { | |||||
| this.uploadFiles = []; | |||||
| this.uploadLength = 0; | |||||
| this.uploadSuccessLength = 0; | |||||
| this.uploadStatusList = []; | |||||
| }, | |||||
| updateFileStatus(file, status, progress, infoCode, failedInfo = "") { | |||||
| this.uploadStatusList.forEach((item, index) => { | |||||
| if (item.uploadUuid === file.upload.uuid) { | |||||
| this.uploadStatusList[index].status = status; | |||||
| this.uploadStatusList[index].progress = progress; | |||||
| this.uploadStatusList[index].infoCode = infoCode; | |||||
| this.uploadStatusList[index].failedInfo = failedInfo; | |||||
| } | |||||
| }); | |||||
| }, | |||||
| calcFileMd5(file) { | |||||
| const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; | |||||
| const chunkSize = md5ChunkSize; | |||||
| const chunks = Math.ceil(file.size / chunkSize); | |||||
| const spark = new SparkMD5.ArrayBuffer(); | |||||
| const fileReader = new FileReader(); | |||||
| file.totalChunkCounts = chunks; | |||||
| if (file.size == 0) { | |||||
| file.totalChunkCounts = 1; | |||||
| } | |||||
| let currentChunk = 0; | |||||
| this.uploadStatusList.push({ | |||||
| uploadUuid: file.upload.uuid, | |||||
| name: file.name, | |||||
| status: this.$t('modelManage.calcFileMd5'), | |||||
| progress: 0, | |||||
| infoCode: 3, | |||||
| }); | |||||
| return new Promise((resolve, reject) => { | |||||
| fileReader.onload = function (e) { | |||||
| spark.append(e.target.result); | |||||
| currentChunk++; | |||||
| if (currentChunk < chunks) { | |||||
| loadNext(); | |||||
| } else { | |||||
| const md5 = spark.end(); | |||||
| spark.destroy(); | |||||
| file.uniqueIdentifier = md5; | |||||
| resolve(md5); | |||||
| } | |||||
| }; | |||||
| fileReader.onerror = function (e) { | |||||
| console.warn(file.name + ': calcFileMd5 went wrong.'); | |||||
| reject(e); | |||||
| }; | |||||
| function loadNext() { | |||||
| const start = currentChunk * chunkSize; | |||||
| const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize; | |||||
| fileReader.readAsArrayBuffer(blobSlice.call(file, start, end)); | |||||
| } | |||||
| loadNext(); | |||||
| }); | |||||
| }, | |||||
| getChunksInfo(file) { | |||||
| return getChunks({ | |||||
| md5: file.uniqueIdentifier, | |||||
| type: this.state.type, | |||||
| modeluuid: this.state.id, | |||||
| file_name: file.name, | |||||
| scene: 'model', | |||||
| }).then(res => { | |||||
| const data = res.data; | |||||
| file.uploadID = data.uploadID; | |||||
| file.uuid = data.uuid; | |||||
| file.uploaded = data.uploaded; | |||||
| file.chunks = data.chunks; | |||||
| file.attachID = data.attachID; | |||||
| file._modelUuid = data.modeluuid; | |||||
| file._modelName = data.modelName; | |||||
| file.realName = data.fileName; | |||||
| return file; | |||||
| }).catch(err => { | |||||
| console.info('getChunksInfo', err); | |||||
| return err; | |||||
| }); | |||||
| }, | |||||
| newUpload(file) { | |||||
| return getNewMultipart({ | |||||
| totalChunkCounts: file.totalChunkCounts, | |||||
| md5: file.uniqueIdentifier, | |||||
| size: file.size, | |||||
| fileType: file.type, | |||||
| type: this.state.type, | |||||
| file_name: file.name, | |||||
| scene: 'model', | |||||
| modeluuid: file.modelUuid, | |||||
| }).then(res => { | |||||
| const data = res.data; | |||||
| file.uploadID = data.uploadID; | |||||
| file.uuid = data.uuid; | |||||
| if (file.uploadID && file.uuid) { | |||||
| file.chunks = ''; | |||||
| this.breakpointUpload(file); | |||||
| } else { | |||||
| this.uploadError(file, info); | |||||
| this.updateFileStatus(file, this.$t('modelManage.uploadFailed'), 0, 2); | |||||
| } | |||||
| return file; | |||||
| }).catch(err => { | |||||
| console.log('getNewMultipart', err); | |||||
| this.uploadError(file, info); | |||||
| this.updateFileStatus(file, this.$t('modelManage.uploadFailed'), 0, 2); | |||||
| return err; | |||||
| }); | |||||
| }, | |||||
| breakpointUpload(file) { | |||||
| const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; | |||||
| const fileReader = new FileReader(); | |||||
| const time = new Date().getTime(); | |||||
| const chunkSize = uploadChunkSize; | |||||
| const chunks = Math.ceil(file.size / chunkSize); | |||||
| const _this = this; | |||||
| let currentChunk = 0; | |||||
| const successChunks = []; | |||||
| const successParts = file.chunks.split(","); | |||||
| for (let i = 0; i < successParts.length; i++) { | |||||
| successChunks[i] = successParts[i].split("-")[0]; | |||||
| } | |||||
| const urls = []; | |||||
| const etags = []; | |||||
| const checkSuccessChunks = () => { | |||||
| const index = successChunks.indexOf((currentChunk + 1).toString()); | |||||
| if (index == -1) { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| const getUploadChunkUrl = async (currentChunk, partSize) => { | |||||
| const res = await getMultipartUrl({ | |||||
| uuid: file.uuid, | |||||
| uploadID: file.uploadID, | |||||
| size: partSize, | |||||
| chunkNumber: currentChunk + 1, | |||||
| type: _this.state.type, | |||||
| file_name: file.name, | |||||
| scene: 'model', | |||||
| }); | |||||
| urls[currentChunk] = res.data.url; | |||||
| }; | |||||
| const uploadMinioNewMethod = async (url, e) => { | |||||
| const xhr = new XMLHttpRequest(); | |||||
| xhr.open("PUT", url, false); | |||||
| if (_this.state.type == 0) { | |||||
| xhr.setRequestHeader("Content-Type", "text/plain"); | |||||
| xhr.send(e.target.result); | |||||
| const etagValue = xhr.getResponseHeader("etag"); | |||||
| etags[currentChunk] = etagValue; | |||||
| } else if (_this.state.type == 1) { | |||||
| xhr.setRequestHeader("Content-Type", ""); | |||||
| xhr.send(e.target.result); | |||||
| const etagValue = xhr.getResponseHeader("ETag"); | |||||
| etags[currentChunk] = etagValue; | |||||
| } | |||||
| } | |||||
| const uploadChunk = async (e) => { | |||||
| try { | |||||
| if (!checkSuccessChunks()) { | |||||
| const start = currentChunk * chunkSize; | |||||
| const partSize = start + chunkSize >= file.size ? file.size - start : chunkSize; | |||||
| // 获取分片上传url | |||||
| await getUploadChunkUrl(currentChunk, partSize); | |||||
| if (urls[currentChunk] != '') { | |||||
| await uploadMinioNewMethod(urls[currentChunk], e); | |||||
| if (etags[currentChunk] != '') { | |||||
| } else { | |||||
| console.log("上传到minio uploadChunk etags[currentChunk] == ''"); // TODO | |||||
| } | |||||
| } else { | |||||
| console.log("uploadChunk urls[currentChunk] != ''"); // TODO | |||||
| } | |||||
| } | |||||
| } catch (error) { | |||||
| console.log(error); | |||||
| } | |||||
| } | |||||
| const completeUpload = async () => { | |||||
| return await setCompleteMultipart({ | |||||
| uuid: file.uuid, | |||||
| uploadID: file.uploadID, | |||||
| file_name: file.name, | |||||
| size: file.size, | |||||
| type: _this.state.type, | |||||
| scene: 'model', | |||||
| modeluuid: file.modelUuid, | |||||
| }); | |||||
| } | |||||
| function loadNext() { | |||||
| const start = currentChunk * chunkSize; | |||||
| const end = start + chunkSize >= file.size ? file.size : start + chunkSize; | |||||
| fileReader.readAsArrayBuffer(blobSlice.call(file, start, end)); | |||||
| } | |||||
| fileReader.onload = async (e) => { | |||||
| try { | |||||
| await uploadChunk(e); | |||||
| fileReader.abort(); | |||||
| currentChunk++; | |||||
| if (currentChunk < chunks) { | |||||
| console.log(`第${currentChunk}个分片上传完成, 开始第${currentChunk + 1}/${chunks}个分片上传`); | |||||
| this.updateFileStatus(file, this.$t('modelManage.uploading'), Number(((currentChunk / chunks) * 100).toFixed(2)), 3); | |||||
| loadNext(); | |||||
| } else { | |||||
| try { | |||||
| await completeUpload(); | |||||
| console.log(`文件上传完成:${file.name} \n分片:${chunks} 大小:${file.size} 用时:${(new Date().getTime() - time) / 1000} s`); | |||||
| this.uploadLength++; | |||||
| this.uploadSuccessLength++; | |||||
| this.updateFileStatus(file, this.$t('modelManage.uploadSuccess'), 100, 0); | |||||
| this.uploadSuccess(file); | |||||
| } catch (err) { | |||||
| const info = this.$t('modelManage.uploadFailed'); | |||||
| console.log(info, file) | |||||
| this.uploadLength++; | |||||
| this.uploadError(file, info); | |||||
| this.updateFileStatus(file, info, Number(((currentChunk / chunks) * 100).toFixed(2)) - 1, 2); | |||||
| } | |||||
| } | |||||
| } catch (err) { | |||||
| console.log(err); | |||||
| const info = this.$t('modelManage.uploadFailed'); | |||||
| console.log(info, file) | |||||
| this.uploadLength++; | |||||
| this.uploadError(file, info); | |||||
| this.updateFileStatus(file, info, Number(((currentChunk / chunks) * 100).toFixed(2)) - 1, 2); | |||||
| } | |||||
| }; | |||||
| console.log("上传分片..."); | |||||
| loadNext(); | |||||
| }, | |||||
| uploadError(file, info) { | |||||
| file.previewTemplate.querySelector('.dz-success-mark').style.opacity = 0; | |||||
| file.previewTemplate.querySelector('.dz-error-mark').style.opacity = 1; | |||||
| file.previewTemplate.querySelector('.dz-error-message span').innerHTML = info; | |||||
| file.previewTemplate.querySelector(".dz-error-message").style.display = 'block'; | |||||
| file.previewTemplate.querySelector(".dz-details").onmouseover = () => { | |||||
| file.previewTemplate.querySelector('.dz-error-message').style.opacity = 1; | |||||
| }; | |||||
| file.previewTemplate.querySelector(".dz-details").onmouseout = () => { | |||||
| file.previewTemplate.querySelector('.dz-error-message').style.opacity = 0; | |||||
| }; | |||||
| this.uploadFinishCheck(file); | |||||
| }, | |||||
| uploadSuccess(file) { | |||||
| file.previewTemplate.querySelector('.dz-error-mark').style.opacity = 0; | |||||
| file.previewTemplate.querySelector('.dz-error-message span').innerHTML = ''; | |||||
| file.previewTemplate.querySelector('.dz-success-mark').style.opacity = 1; | |||||
| file.previewTemplate.querySelector(".dz-error-message").style.display = 'none'; | |||||
| file.previewTemplate.querySelector(".dz-details").onmouseover = null; | |||||
| file.previewTemplate.querySelector(".dz-details").onmouseout = null; | |||||
| this.uploadFinishCheck(file); | |||||
| }, | |||||
| uploadFinishCheck(file) { | |||||
| console.log('uploadFinishCheck', file, this.uploadLength, '/', this.uploadFiles.length); | |||||
| if (this.uploadLength === this.uploadFiles.length && this.uploadFiles.length != 0) { | |||||
| console.log('All file has finish, success ' + this.uploadSuccessLength); | |||||
| this.uploading = false; | |||||
| if (this.uploadSuccessLength == this.uploadLength) { | |||||
| window.setTimeout(() => { | |||||
| this.goDetail(); | |||||
| }, 1000); | |||||
| } else { | |||||
| if (this.uploadSuccessLength > 0) { | |||||
| this.initModelData(); | |||||
| } | |||||
| } | |||||
| } | |||||
| }, | |||||
| submit() { | |||||
| const fileList = this.dropzoneHandler.getAcceptedFiles(); | |||||
| if (!fileList.length) return; | |||||
| for (let i = 0, iLen = fileList.length; i < iLen; i++) { | |||||
| if (!this.checkFiles(fileList[i], true)) return; | |||||
| } | |||||
| this.resetFileStatus(); | |||||
| this.uploadFiles = fileList; | |||||
| this.uploading = true; | |||||
| for (let i = 0, iLen = fileList.length; i < iLen; i++) { | |||||
| const file = fileList[i]; | |||||
| file.modelUuid = this.state.id; | |||||
| file.modelName = this.state.name; | |||||
| this.calcFileMd5(file).then(res => { // 计算MD5 | |||||
| this.getChunksInfo(file).then(res => { // 获取Chunk信息 | |||||
| if (file.uploadID == '' || file.uuid == '') { // 未上传过 | |||||
| this.newUpload(file); | |||||
| } else if (file.uploaded == '1') { // 已上传成功 | |||||
| if (file.attachID == '0') { // 删除数据集记录,未删除文件 | |||||
| // await addAttachment(file); | |||||
| console.log(`file.attachID == '0'`); | |||||
| } | |||||
| this.uploadLength++; | |||||
| // 同一模型上传同一个文件 | |||||
| if (file._modelUuid) { | |||||
| const info = `${this.$t('modelManage.fileHasAlreadyInTheModel')} ${file._modelName}`; | |||||
| this.uploadError(file, info); | |||||
| this.updateFileStatus(file, this.$t('modelManage.uploadFailed'), 0, 1, info); | |||||
| } else { // 秒传 | |||||
| this.uploadSuccessLength++; | |||||
| this.updateFileStatus(file, this.$t('modelManage.uploadSuccess'), 100, 0); | |||||
| this.uploadSuccess(file); | |||||
| } | |||||
| console.log(file.name, '文件处理完成'); | |||||
| } else { // 断点续传 | |||||
| this.breakpointUpload(file); | |||||
| } | |||||
| }).catch(err => { | |||||
| console.info('getChunksInfo', err); | |||||
| this.uploadLength++; | |||||
| this.uploadError(file, this.$t('modelManage.uploadFailed')); | |||||
| this.updateFileStatus(file, this.$t('modelManage.uploadFailed'), 0, 2); | |||||
| }); | |||||
| }).catch(err => { | |||||
| console.info('calcFileMd5', err); | |||||
| this.uploadLength++; | |||||
| this.uploadError(file, this.$t('modelManage.uploadFailed')); | |||||
| this.updateFileStatus(file, this.$t('modelManage.uploadFailed'), 0, 2); | |||||
| }); | |||||
| } | |||||
| }, | |||||
| cancel() { | |||||
| if (this.type == '1') { | |||||
| this.goDetail(); | |||||
| return; | |||||
| } | |||||
| const list = window.location.href.split('/'); | |||||
| list.pop(); | |||||
| list.push('show_model'); | |||||
| window.location.href = list.join('/'); | |||||
| }, | |||||
| goDetail() { | |||||
| const list = window.location.href.split('/'); | |||||
| list.pop(); | |||||
| list.push('show_model_info'); | |||||
| window.location.href = list.join('/') + '?name=' + this.state.name; | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| this.initModelData(); | |||||
| this.initDropZone(); | |||||
| }, | |||||
| beforeDestroy() { | |||||
| }, | |||||
| }; | |||||
| </script> | |||||
| <style scoped lang="less"> | |||||
| .header { | |||||
| height: 45px; | |||||
| border-color: rgb(212, 212, 213); | |||||
| border-width: 1px; | |||||
| border-style: solid; | |||||
| border-radius: 5px 5px 0px 0px; | |||||
| font-size: 14px; | |||||
| background: rgb(240, 240, 240); | |||||
| display: flex; | |||||
| align-items: center; | |||||
| .title { | |||||
| font-weight: 600; | |||||
| font-size: 16px; | |||||
| color: rgb(16, 16, 16); | |||||
| margin-left: 10px; | |||||
| } | |||||
| } | |||||
| .content { | |||||
| margin-top: -1px; | |||||
| border-color: rgb(212, 212, 213); | |||||
| border-width: 1px; | |||||
| border-style: solid; | |||||
| padding: 30px 0; | |||||
| border-top: none; | |||||
| .guide-c { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| margin-bottom: 20px; | |||||
| .step { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| color: rgb(136, 136, 136); | |||||
| .num { | |||||
| border: 1px solid rgb(136, 136, 136); | |||||
| width: 34px; | |||||
| height: 34px; | |||||
| font-size: 24px; | |||||
| text-align: center; | |||||
| line-height: 34px; | |||||
| border-radius: 17px; | |||||
| margin-right: 8px; | |||||
| } | |||||
| .txt { | |||||
| font-weight: 600; | |||||
| } | |||||
| &.focused { | |||||
| color: rgb(22, 132, 252); | |||||
| .num { | |||||
| border-color: rgb(22, 132, 252); | |||||
| } | |||||
| } | |||||
| } | |||||
| .line { | |||||
| height: 2px; | |||||
| width: 50px; | |||||
| background-color: rgb(187, 187, 187); | |||||
| margin: 0 10px; | |||||
| } | |||||
| } | |||||
| .row-c { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| flex-direction: column; | |||||
| margin: 0 auto; | |||||
| .row { | |||||
| width: 100%; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| margin: 8px 0; | |||||
| margin-left: -190px; | |||||
| .r-title { | |||||
| text-align: right; | |||||
| font-size: .92857143em; | |||||
| font-weight: 700; | |||||
| color: rgba(0, 0, 0, .87); | |||||
| width: 200px; | |||||
| margin-right: 28px; | |||||
| position: relative; | |||||
| .required { | |||||
| &::after { | |||||
| position: absolute; | |||||
| margin: -0.2em 0 0 0.2em; | |||||
| content: '*'; | |||||
| color: #db2828; | |||||
| } | |||||
| } | |||||
| } | |||||
| .r-content { | |||||
| flex: 1; | |||||
| .cluster-type-btn { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| border: 1px solid #DCDFE6; | |||||
| height: 36px; | |||||
| padding: 10px; | |||||
| cursor: pointer; | |||||
| border-radius: 4px; | |||||
| .icon { | |||||
| margin-right: 5px; | |||||
| } | |||||
| &.focused { | |||||
| border-color: rgb(50, 145, 248); | |||||
| color: rgb(50, 145, 248); | |||||
| cursor: default; | |||||
| .icon { | |||||
| :not([stroke]) { | |||||
| fill: rgb(50, 145, 248); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .not-allowed-placeholder { | |||||
| position: absolute; | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| z-index: 20; | |||||
| cursor: no-drop; | |||||
| top: 0; | |||||
| } | |||||
| .dropzone { | |||||
| min-height: 186px !important; | |||||
| /deep/ .dz-default.dz-message { | |||||
| margin: 76px 0 !important; | |||||
| } | |||||
| /deep/ .dz-remove { | |||||
| margin-top: 10px !important; | |||||
| } | |||||
| } | |||||
| .input-disabled { | |||||
| /deep/ .el-input__inner { | |||||
| background-color: #f5f5f6 !important; | |||||
| color: #888888 !important; | |||||
| } | |||||
| } | |||||
| /deep/ .dz-progress { | |||||
| display: none; | |||||
| } | |||||
| .success { | |||||
| color: #21ba45; | |||||
| font-size: 16px; | |||||
| margin-right: 0.5rem; | |||||
| } | |||||
| .failed { | |||||
| color: red; | |||||
| font-size: 16px; | |||||
| margin-right: 0.5rem; | |||||
| } | |||||
| .datast-upload-progress { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| } | |||||
| .datast-upload-progress .dataset-name { | |||||
| text-align: right; | |||||
| width: 200px; | |||||
| margin-right: 1rem; | |||||
| } | |||||
| .datast-upload-progress .dataset-progress { | |||||
| flex: 1; | |||||
| } | |||||
| .datast-upload-progress .dataset-status { | |||||
| width: 140px; | |||||
| margin-left: 1rem; | |||||
| } | |||||
| .datast-upload-progress .dataset-status .status-flex { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| } | |||||
| /deep/ .el-progress-bar__inner { | |||||
| background-color: #21ba45; | |||||
| } | |||||
| .el-select-dropdown__item.selected { | |||||
| color: #85b7d9; | |||||
| } | |||||
| /deep/ .el-button { | |||||
| background-color: #e0e1e2; | |||||
| color: rgba(0, 0, 0, .6); | |||||
| border-color: transparent; | |||||
| transition: opacity .1s ease, background-color .1s ease, color .1s ease, box-shadow .1s ease, background .1s ease, -webkit-box-shadow .1s ease; | |||||
| will-change: auto; | |||||
| -webkit-tap-highlight-color: transparent; | |||||
| &:hover { | |||||
| border-color: transparent; | |||||
| background-color: #cacbcd; | |||||
| color: rgba(0, 0, 0, .8); | |||||
| } | |||||
| &:focus { | |||||
| background-color: #cacbcd; | |||||
| color: rgba(0, 0, 0, .8); | |||||
| border-color: transparent; | |||||
| } | |||||
| &:active { | |||||
| background-color: #babbbc; | |||||
| color: rgba(0, 0, 0, .9); | |||||
| border-color: transparent; | |||||
| } | |||||
| &.green { | |||||
| background-color: #5bb973; | |||||
| color: #fff; | |||||
| &:hover { | |||||
| background-color: #16ab39; | |||||
| border-color: transparent; | |||||
| } | |||||
| &:focus { | |||||
| background-color: #0ea432; | |||||
| border-color: transparent; | |||||
| } | |||||
| &:active { | |||||
| background-color: #198f35; | |||||
| border-color: transparent; | |||||
| } | |||||
| } | |||||
| } | |||||
| /deep/ .el-select { | |||||
| .is-focus { | |||||
| .el-input__inner { | |||||
| border-color: #85b7d9; | |||||
| } | |||||
| } | |||||
| } | |||||
| /deep/ .el-input__inner { | |||||
| &:focus { | |||||
| border-color: #85b7d9; | |||||
| } | |||||
| } | |||||
| /deep/ .el-textarea__inner { | |||||
| &:focus { | |||||
| border-color: #85b7d9; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @@ -0,0 +1,17 @@ | |||||
| import Vue from 'vue'; | |||||
| import ElementUI from 'element-ui'; | |||||
| import 'element-ui/lib/theme-chalk/index.css'; | |||||
| import localeEn from 'element-ui/lib/locale/lang/en'; | |||||
| import localeZh from 'element-ui/lib/locale/lang/zh-CN'; | |||||
| import { i18n, lang } from '~/langs'; | |||||
| import App from './modelmanage-local-create-1.vue'; | |||||
| Vue.use(ElementUI, { | |||||
| locale: lang === 'zh-CN' ? localeZh : localeEn, | |||||
| size: 'small', | |||||
| }); | |||||
| new Vue({ | |||||
| i18n, | |||||
| render: (h) => h(App), | |||||
| }).$mount('#__vue-root'); | |||||
| @@ -0,0 +1,17 @@ | |||||
| import Vue from 'vue'; | |||||
| import ElementUI from 'element-ui'; | |||||
| import 'element-ui/lib/theme-chalk/index.css'; | |||||
| import localeEn from 'element-ui/lib/locale/lang/en'; | |||||
| import localeZh from 'element-ui/lib/locale/lang/zh-CN'; | |||||
| import { i18n, lang } from '~/langs'; | |||||
| import App from './modelmanage-local-create-2.vue'; | |||||
| Vue.use(ElementUI, { | |||||
| locale: lang === 'zh-CN' ? localeZh : localeEn, | |||||
| size: 'small', | |||||
| }); | |||||
| new Vue({ | |||||
| i18n, | |||||
| render: (h) => h(App), | |||||
| }).$mount('#__vue-root'); | |||||
| @@ -69,7 +69,9 @@ | |||||
| </div> | </div> | ||||
| <div class="content"> | <div class="content"> | ||||
| <el-select v-model="dataInfo.SpecIds" multiple collapse-tags class="specSel"> | <el-select v-model="dataInfo.SpecIds" multiple collapse-tags class="specSel"> | ||||
| <el-option v-for="item in specsList" :key="item.k" :label="item.v" :value="item.k" /> | |||||
| <el-option v-for="item in specsList" :label="item.v" :key="item.k" :value="item.k"> | |||||
| <span v-html="item.v"></span> | |||||
| </el-option> | |||||
| </el-select> | </el-select> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -87,7 +89,7 @@ | |||||
| </template> | </template> | ||||
| <script> | <script> | ||||
| import BaseDialog from '~/components/BaseDialog.vue'; | import BaseDialog from '~/components/BaseDialog.vue'; | ||||
| import { getResQueueCode, getResSpecificationList, addResScene, updateResScene } from '~/apis/modules/resources'; | |||||
| import { getResQueueCode, getResSpecificationListAll, addResScene, updateResScene } from '~/apis/modules/resources'; | |||||
| import { JOB_TYPE, CLUSTERS, ACC_CARD_TYPE, SPECIFICATION_STATUS } from '~/const'; | import { JOB_TYPE, CLUSTERS, ACC_CARD_TYPE, SPECIFICATION_STATUS } from '~/const'; | ||||
| import { getListValueWithKey } from '~/utils'; | import { getListValueWithKey } from '~/utils'; | ||||
| @@ -167,21 +169,21 @@ export default { | |||||
| const params = { | const params = { | ||||
| cluster: this.dataInfo.Cluster, | cluster: this.dataInfo.Cluster, | ||||
| queue: this.dataInfo.QueueId === '-1' ? '' : this.dataInfo.QueueId, | queue: this.dataInfo.QueueId === '-1' ? '' : this.dataInfo.QueueId, | ||||
| status: 2, | |||||
| page: 1, | |||||
| // status: 2, | |||||
| // page: 1, | |||||
| }; | }; | ||||
| return getResSpecificationList(params).then(res => { | |||||
| return getResSpecificationListAll(params).then(res => { | |||||
| res = res.data; | res = res.data; | ||||
| if (res.Code === 0) { | if (res.Code === 0) { | ||||
| const list = res.Data.List; | const list = res.Data.List; | ||||
| const data = list.map((item) => { | const data = list.map((item) => { | ||||
| const Queue = item.Queue; | const Queue = item.Queue; | ||||
| const Spec = item.Spec; | const Spec = item.Spec; | ||||
| // const NGPU = `${Queue.ComputeResource}:${Spec.AccCardsNum === 0 ? '0' : Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Queue.AccCardType)}`; | |||||
| const NGPU = `${Queue.ComputeResource}:${Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Queue.AccCardType)}`; | const NGPU = `${Queue.ComputeResource}:${Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Queue.AccCardType)}`; | ||||
| const statusStr = Spec.Status != '2' ? `<span style="color:rgb(245, 34, 45)">(${getListValueWithKey(this.statusList, Spec.Status.toString())})</span>` : ''; | |||||
| return { | return { | ||||
| k: Spec.ID, | k: Spec.ID, | ||||
| v: `${NGPU}, CPU:${Spec.CpuCores}, ${this.$t('resourcesManagement.gpuMem')}:${Spec.GPUMemGiB}GB, ${this.$t('resourcesManagement.mem')}:${Spec.MemGiB}GB, ${this.$t('resourcesManagement.shareMem')}:${Spec.ShareMemGiB}GB, ${this.$t('resourcesManagement.unitPrice')}:${Spec.UnitPrice}${this.$t('resourcesManagement.point_hr')}`, | |||||
| v: `${NGPU}, CPU:${Spec.CpuCores}, ${this.$t('resourcesManagement.gpuMem')}:${Spec.GPUMemGiB}GB, ${this.$t('resourcesManagement.mem')}:${Spec.MemGiB}GB, ${this.$t('resourcesManagement.shareMem')}:${Spec.ShareMemGiB}GB, ${this.$t('resourcesManagement.unitPrice')}:${Spec.UnitPrice}${this.$t('resourcesManagement.point_hr')}${statusStr}`, | |||||
| } | } | ||||
| }); | }); | ||||
| this.specsList.splice(0, Infinity, ...data); | this.specsList.splice(0, Infinity, ...data); | ||||
| @@ -64,7 +64,7 @@ | |||||
| header-align="center" min-width="180"> | header-align="center" min-width="180"> | ||||
| <template slot-scope="scope"> | <template slot-scope="scope"> | ||||
| <div v-for="item in scope.row.SpecsList" :key="item.k"> | <div v-for="item in scope.row.SpecsList" :key="item.k"> | ||||
| <span>{{ item.v }}</span> | |||||
| <span v-html="item.v"></span> | |||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| </el-table-column> | </el-table-column> | ||||
| @@ -100,7 +100,7 @@ | |||||
| <script> | <script> | ||||
| import SceneDialog from '../components/SceneDialog.vue'; | import SceneDialog from '../components/SceneDialog.vue'; | ||||
| import { getQueueList, getResQueueCode, getResSceneList, updateResScene, getAiCenterList } from '~/apis/modules/resources'; | import { getQueueList, getResQueueCode, getResSceneList, updateResScene, getAiCenterList } from '~/apis/modules/resources'; | ||||
| import { JOB_TYPE, CLUSTERS, ACC_CARD_TYPE } from '~/const'; | |||||
| import { JOB_TYPE, CLUSTERS, ACC_CARD_TYPE, SPECIFICATION_STATUS } from '~/const'; | |||||
| import { getListValueWithKey } from '~/utils'; | import { getListValueWithKey } from '~/utils'; | ||||
| import { formatDate } from 'element-ui/lib/utils/date-util'; | import { formatDate } from 'element-ui/lib/utils/date-util'; | ||||
| @@ -117,6 +117,7 @@ export default { | |||||
| selAiCenter: '', | selAiCenter: '', | ||||
| aiCenterList: [{ k: '', v: this.$t('resourcesManagement.allAiCenter') }], | aiCenterList: [{ k: '', v: this.$t('resourcesManagement.allAiCenter') }], | ||||
| accCardTypeList: [...ACC_CARD_TYPE], | accCardTypeList: [...ACC_CARD_TYPE], | ||||
| statusList: [{ k: '', v: this.$t('resourcesManagement.allStatus') }, ...SPECIFICATION_STATUS], | |||||
| loading: false, | loading: false, | ||||
| tableData: [], | tableData: [], | ||||
| pageInfo: { | pageInfo: { | ||||
| @@ -191,11 +192,11 @@ export default { | |||||
| let cluster = ''; | let cluster = ''; | ||||
| for (let i = 0, iLen = Specs.length; i < iLen; i++) { | for (let i = 0, iLen = Specs.length; i < iLen; i++) { | ||||
| const Spec = Specs[i]; | const Spec = Specs[i]; | ||||
| // const NGPU = `${Spec.ComputeResource}:${Spec.AccCardsNum === 0 ? '0' : Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Spec.AccCardType)}`; | |||||
| const NGPU = `${Spec.ComputeResource}:${Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Spec.AccCardType)}`; | const NGPU = `${Spec.ComputeResource}:${Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Spec.AccCardType)}`; | ||||
| const statusStr = Spec.Status != '2' ? `<span style="color:rgb(245, 34, 45)">(${getListValueWithKey(this.statusList, Spec.Status.toString())})</span>` : ''; | |||||
| specsList.push({ | specsList.push({ | ||||
| k: Spec.ID, | k: Spec.ID, | ||||
| v: `${NGPU}, CPU:${Spec.CpuCores}, ${this.$t('resourcesManagement.gpuMem')}:${Spec.GPUMemGiB}GB, ${this.$t('resourcesManagement.mem')}:${Spec.MemGiB}GB, ${this.$t('resourcesManagement.shareMem')}:${Spec.ShareMemGiB}GB, ${this.$t('resourcesManagement.unitPrice')}:${Spec.UnitPrice}${this.$t('resourcesManagement.point_hr')}`, | |||||
| v: `${NGPU}, CPU:${Spec.CpuCores}, ${this.$t('resourcesManagement.gpuMem')}:${Spec.GPUMemGiB}GB, ${this.$t('resourcesManagement.mem')}:${Spec.MemGiB}GB, ${this.$t('resourcesManagement.shareMem')}:${Spec.ShareMemGiB}GB, ${this.$t('resourcesManagement.unitPrice')}:${Spec.UnitPrice}${this.$t('resourcesManagement.point_hr')}${statusStr}`, | |||||
| }); | }); | ||||
| cluster = Spec.Cluster; | cluster = Spec.Cluster; | ||||
| if (queueIds.indexOf(Spec.QueueId) < 0) { | if (queueIds.indexOf(Spec.QueueId) < 0) { | ||||
| @@ -1,7 +1,41 @@ | |||||
| import { i18n } from '~/langs'; | |||||
| import { ACC_CARD_TYPE } from '~/const'; | |||||
| export const getListValueWithKey = (list, key, k = 'k', v = 'v') => { | export const getListValueWithKey = (list, key, k = 'k', v = 'v') => { | ||||
| for (let i = 0, iLen = list.length; i < iLen; i++) { | for (let i = 0, iLen = list.length; i < iLen; i++) { | ||||
| const listI = list[i]; | const listI = list[i]; | ||||
| if (listI[k] === key) return listI[v]; | if (listI[k] === key) return listI[v]; | ||||
| } | } | ||||
| return ''; | |||||
| return key; | |||||
| }; | |||||
| export const getUrlSearchParams = () => { | |||||
| const params = new URLSearchParams(location.search); | |||||
| const obj = {}; | |||||
| params.forEach((value, key) => { | |||||
| obj[key] = value; | |||||
| }); | |||||
| return obj; | |||||
| }; | |||||
| export const transFileSize = (srcSize) => { | |||||
| if (null == srcSize || srcSize == '') { | |||||
| return '0 Bytes'; | |||||
| } | |||||
| const unitArr = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; | |||||
| srcSize = parseFloat(srcSize); | |||||
| const index = Math.floor(Math.log(srcSize) / Math.log(1024)); | |||||
| const size = (srcSize / Math.pow(1024, index)).toFixed(2); | |||||
| return size + ' ' + unitArr[index]; | |||||
| }; | |||||
| export const renderSpecStr = (spec, showPoint) => { | |||||
| if (!spec) return ''; | |||||
| var ngpu = `${spec.ComputeResource}: ${spec.AccCardsNum + '*' + getListValueWithKey(ACC_CARD_TYPE, spec.AccCardType)}`; | |||||
| var gpuMemStr = spec.GPUMemGiB != 0 ? `${i18n.t('resourcesManagement.gpuMem')}: ${spec.GPUMemGiB}GB, ` : ''; | |||||
| var sharedMemStr = spec.ShareMemGiB != 0 ? `, ${i18n.t('resourcesManagement.shareMem')}: ${spec.ShareMemGiB}GB` : ''; | |||||
| var pointStr = showPoint ? `, ${spec.UnitPrice == 0 ? i18n.t('resourcesManagement.free') : spec.UnitPrice + i18n.t('resourcesManagement.point_hr')}` : ''; | |||||
| var specStr = `${ngpu}, CPU: ${spec.CpuCores}, ${gpuMemStr}${i18n.t('resourcesManagement.mem')}: ${spec.MemGiB}GB${sharedMemStr}${pointStr}`; | |||||
| return specStr; | |||||
| }; | }; | ||||