package models import ( "code.gitea.io/gitea/modules/timeutil" "errors" "xorm.io/builder" ) const ( Exclusive = iota + 1 NotExclusive ) type ResourceScene struct { ID int64 `xorm:"pk autoincr"` SceneName string JobType string IsExclusive bool ExclusiveOrg string CreatedTime timeutil.TimeStamp `xorm:"created"` CreatedBy int64 UpdatedTime timeutil.TimeStamp `xorm:"updated"` UpdatedBy int64 DeleteTime timeutil.TimeStamp `xorm:"deleted"` DeletedBy int64 } type ResourceSceneSpec struct { ID int64 `xorm:"pk autoincr"` SceneId int64 `xorm:"unique(idx_scene_spec)"` SpecId int64 `xorm:"unique(idx_scene_spec)"` CreatedTime timeutil.TimeStamp `xorm:"created"` } type ResourceSceneReq struct { ID int64 SceneName string JobType string IsExclusive bool ExclusiveOrg string CreatorId int64 SpecIds []int64 } type SearchResourceSceneOptions struct { ListOptions JobType string IsExclusive int AiCenterCode string QueueId int64 } type ResourceSceneListRes struct { TotalSize int64 List []ResourceSceneRes } func NewResourceSceneListRes(totalSize int64, list []ResourceSceneRes) *ResourceSceneListRes { return &ResourceSceneListRes{ TotalSize: totalSize, List: list, } } type ResourceSceneRes struct { ID int64 SceneName string JobType JobType IsExclusive bool ExclusiveOrg string Specs []ResourceSpecWithSceneId } func (ResourceSceneRes) TableName() string { return "resource_scene" } type ResourceSceneBriefRes struct { ID int64 SceneName string } func (ResourceSceneBriefRes) TableName() string { return "resource_scene" } type ResourceSpecWithSceneId struct { ID int64 SourceSpecId string AccCardsNum int CpuCores int MemGiB float32 GPUMemGiB float32 ShareMemGiB float32 UnitPrice int Status int UpdatedTime timeutil.TimeStamp SceneId int64 //queue Cluster string AiCenterCode string AiCenterName string QueueCode string QueueId int64 ComputeResource string AccCardType string } func (ResourceSpecWithSceneId) TableName() string { return "resource_specification" } func InsertResourceScene(r ResourceSceneReq) error { sess := x.NewSession() defer sess.Close() //check specs := make([]ResourceSpecification, 0) cond := builder.In("id", r.SpecIds) if err := sess.Where(cond).Find(&specs); err != nil { return err } if len(specs) < len(r.SpecIds) { return errors.New("specIds not correct") } rs := ResourceScene{ SceneName: r.SceneName, JobType: r.JobType, IsExclusive: r.IsExclusive, ExclusiveOrg: r.ExclusiveOrg, CreatedBy: r.CreatorId, UpdatedBy: r.CreatorId, } _, err := sess.InsertOne(&rs) if err != nil { sess.Rollback() return err } if len(r.SpecIds) == 0 { return sess.Commit() } rss := make([]ResourceSceneSpec, len(r.SpecIds)) for i, v := range r.SpecIds { rss[i] = ResourceSceneSpec{ SceneId: rs.ID, SpecId: v, } } _, err = sess.Insert(&rss) if err != nil { sess.Rollback() return err } return sess.Commit() } func UpdateResourceScene(r ResourceSceneReq) error { sess := x.NewSession() var err error defer func() { if err != nil { sess.Rollback() } sess.Close() }() // find old scene old := ResourceScene{} if has, _ := sess.ID(r.ID).Get(&old); !has { return errors.New("ResourceScene not exist") } //check specification specs := make([]ResourceSpecification, 0) cond := builder.In("id", r.SpecIds) if err := sess.Where(cond).Find(&specs); err != nil { return err } if len(specs) < len(r.SpecIds) { return errors.New("specIds not correct") } //update scene rs := ResourceScene{ SceneName: r.SceneName, IsExclusive: r.IsExclusive, ExclusiveOrg: r.ExclusiveOrg, } if _, err = sess.ID(r.ID).UseBool("is_exclusive").Update(&rs); err != nil { return err } //delete scene spec relation if _, err = sess.Where("scene_id = ? ", r.ID).Delete(&ResourceSceneSpec{}); err != nil { sess.Rollback() return err } if len(r.SpecIds) == 0 { return sess.Commit() } //build new scene spec relation rss := make([]ResourceSceneSpec, len(r.SpecIds)) for i, v := range r.SpecIds { rss[i] = ResourceSceneSpec{ SceneId: r.ID, SpecId: v, } } if _, err = sess.Insert(&rss); err != nil { sess.Rollback() return err } return sess.Commit() } func DeleteResourceScene(sceneId int64) error { sess := x.NewSession() var err error defer func() { if err != nil { sess.Rollback() } sess.Close() }() if _, err = sess.ID(sceneId).Delete(&ResourceScene{}); err != nil { return err } if _, err = sess.Where("scene_id = ? ", sceneId).Delete(&ResourceSceneSpec{}); err != nil { return err } return sess.Commit() } func SearchResourceScene(opts SearchResourceSceneOptions) (int64, []ResourceSceneRes, error) { var cond = builder.NewCond() if opts.Page <= 0 { opts.Page = 1 } if opts.JobType != "" { cond = cond.And(builder.Eq{"resource_scene.job_type": opts.JobType}) } if opts.IsExclusive == Exclusive { cond = cond.And(builder.Eq{"resource_scene.is_exclusive": 1}) } else if opts.IsExclusive == NotExclusive { cond = cond.And(builder.Eq{"resource_scene.is_exclusive": 0}) } if opts.AiCenterCode != "" { cond = cond.And(builder.Eq{"resource_queue.ai_center_code": opts.AiCenterCode}) } if opts.QueueId > 0 { cond = cond.And(builder.Eq{"resource_queue.id": opts.QueueId}) } cond = cond.And(builder.NewCond().Or(builder.Eq{"resource_scene.delete_time": 0}).Or(builder.IsNull{"resource_scene.delete_time"})) cols := []string{"resource_scene.id", "resource_scene.scene_name", "resource_scene.job_type", "resource_scene.is_exclusive", "resource_scene.exclusive_org"} count, err := x.Where(cond). Distinct("resource_scene.id"). Join("INNER", "resource_scene_spec", "resource_scene_spec.scene_id = resource_scene.id"). Join("INNER", "resource_specification", "resource_specification.id = resource_scene_spec.spec_id"). Join("INNER", "resource_queue", "resource_queue.id = resource_specification.queue_id"). Count(&ResourceSceneRes{}) if err != nil { return 0, nil, err } r := make([]ResourceSceneRes, 0) if err = x.Where(cond).Distinct(cols...). Join("INNER", "resource_scene_spec", "resource_scene_spec.scene_id = resource_scene.id"). Join("INNER", "resource_specification", "resource_specification.id = resource_scene_spec.spec_id"). Join("INNER", "resource_queue", "resource_queue.id = resource_specification.queue_id"). Desc("resource_scene.id"). Limit(opts.PageSize, (opts.Page-1)*opts.PageSize). Find(&r); err != nil { return 0, nil, err } if len(r) == 0 { return 0, r, err } //find related specs sceneIds := make([]int64, 0, len(r)) for _, v := range r { sceneIds = append(sceneIds, v.ID) } specs := make([]ResourceSpecWithSceneId, 0) if err := x.Cols("resource_specification.id", "resource_specification.source_spec_id", "resource_specification.acc_cards_num", "resource_specification.cpu_cores", "resource_specification.mem_gi_b", "resource_specification.gpu_mem_gi_b", "resource_specification.share_mem_gi_b", "resource_specification.unit_price", "resource_specification.status", "resource_specification.updated_time", "resource_scene_spec.scene_id", "resource_queue.cluster", "resource_queue.ai_center_code", "resource_queue.acc_card_type", "resource_queue.id as queue_id", "resource_queue.compute_resource", "resource_queue.queue_code", "resource_queue.ai_center_name", ).In("resource_scene_spec.scene_id", sceneIds). Join("INNER", "resource_scene_spec", "resource_scene_spec.spec_id = resource_specification.id"). Join("INNER", "resource_queue", "resource_queue.ID = resource_specification.queue_id"). OrderBy("resource_specification.acc_cards_num"). Find(&specs); err != nil { return 0, nil, err } specsMap := make(map[int64][]ResourceSpecWithSceneId, 0) for _, v := range specs { if _, ok := specsMap[v.SceneId]; !ok { specsMap[v.SceneId] = []ResourceSpecWithSceneId{v} } else { specsMap[v.SceneId] = append(specsMap[v.SceneId], v) } } for i, v := range r { s := specsMap[v.ID] if s == nil { s = make([]ResourceSpecWithSceneId, 0) } r[i].Specs = s } return count, r, nil }