| @@ -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 | ||||
| } | } | ||||
| @@ -168,6 +168,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 { | ||||
| @@ -269,10 +270,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, | ||||
| @@ -317,9 +314,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 | ||||
| @@ -384,6 +378,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") | ||||
| @@ -136,6 +136,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) | ||||
| @@ -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) | ||||
| @@ -1487,6 +1488,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) | ||||
| } | } | ||||
| @@ -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,48 @@ 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 | |||||
| _, 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 +238,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) | ||||
| @@ -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({ | ||||
| @@ -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) { | ||||