add resource spec

Signed-off-by: jagger <cossjie@foxmail.com>
This commit is contained in:
jagger 2025-05-21 09:54:17 +08:00
parent f2cc26264d
commit 6ad5619965
20 changed files with 8259 additions and 6950 deletions

View File

@ -1392,3 +1392,58 @@ type ResourceCostRecord {
Status int `json:"status" gorm:"column:status"`
UsageHours string `json:"usageHours" gorm:"column:usage_hours"`
}
type ResourceSpecReq {
ClusterId string `form:"clusterId"`
Type string `form:"type,optional"`
Name string `form:"name,optional"`
Status string `form:"status,optional"`
changeType string `form:"changeType,optional"`
PageInfo
}
type IdReq {
Id string `form:"id,optional" json:"id,optional"`
}
type DeletePathId {
Id string `path:"id"`
}
type ResourceSpecResp {
Data []ResourceSpec `json:"resourceSpec"`
PageInfo
}
type ResourceSpec {
Id int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
Type string `json:"type" gorm:"column:type"`
Name string `json:"name" gorm:"column:name"`
TotalCount int64 `json:"totalCount" gorm:"column:total_count"`
AvailableCount int64 `json:"availableCount" gorm:"column:available_count"`
ChangeType int32 `json:"changeType" gorm:"column:change_type"`
Status int32 `json:"status" gorm:"column:status"`
Region string `json:"region" gorm:"column:region"`
ClusterId string `json:"clusterId" gorm:"column:cluster_id"`
CostPerUnit float64 `json:"costPerUnit" gorm:"column:cost_per_unit"`
CostType string `json:"costType" gorm:"column:cost_type"` //计费类型hourly, daily, monthly,perUse
UserId string `json:"userId" gorm:"column:user_id"`
CreateTime string `json:"createTime" gorm:"column:create_time"`
UpdateTime string `json:"updateTime" gorm:"column:update_time"`
BaseResourceSpecs []BaseResourceSpec `json:"baseResourceSpec" gorm:"foreignKey:ResourceSpecId"`
}
type BaseResourceSpec {
Id int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
ResourceSpecId int64 `json:"resourceSpecId" gorm:"column:resource_spec_id"`
Type string `json:"type" gorm:"column:type"`
Name string `json:"name" gorm:"column:name"`
TotalValue float64 `json:"totalValue" gorm:"column:total_value"`
TotalUnit string `json:"totalUnit" gorm:"column:total_unit"`
AvailableValue float64 `json:"availableValue" gorm:"column:available_value"`
AvailableUnit string `json:"availableUnit" gorm:"column:available_unit"`
UserId string `json:"userId" gorm:"column:user_id"`
CreateTime string `json:"createTime" gorm:"column:create_time"`
UpdateTime string `json:"updateTime" gorm:"column:update_time"`
}

View File

@ -178,6 +178,26 @@ service pcm {
@doc "根据集群id获取集群信息"
@handler getClusterByIdHandler
get /core/getClusterById (getClusterByIdReq) returns (getClusterByIdResp)
@doc "获取指定集群资源规格列表"
@handler getClusterResourceSpecHandler
get /core/ai/resourceSpec/list (ResourceSpecReq) returns (PageResult)
@doc "获取指定资源规格详情"
@handler detailResourceSpecHandler
get /core/ai/resourceSpec/detail (IdReq) returns (ResourceSpec)
@doc "取消资源规格告警"
@handler cancelResourceSpecAlarmHandler
put /core/ai/resourceSpec/cancelAlarm (IdReq) returns (CommonResp)
@doc "编辑资源规格"
@handler editResourceSpecHandler
put /core/ai/resourceSpec/edit (ResourceSpec) returns (CommonResp)
@doc "删除资源规格"
@handler deleteResourceSpecHandler
delete /core/ai/resourceSpec/delete/:id (DeletePathId) returns (CommonResp)
}
//hpc二级接口
@ -415,7 +435,7 @@ service pcm {
@doc "文本识别"
@handler ChatHandler
post /ai/chat (ChatReq) returns (ChatResult)
/******chat end***********/
/******chat end***********/
}
//screen接口
@ -1104,4 +1124,5 @@ service pcm {
@handler scheduleSituationHandler
get /monitoring/schedule/situation returns (scheduleSituationResp)
}
}

View File

@ -0,0 +1,24 @@
package core
import (
"github.com/zeromicro/go-zero/rest/httpx"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/logic/core"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/repository/result"
"net/http"
)
func CancelResourceSpecAlarmHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.IdReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
l := core.NewCancelResourceSpecAlarmLogic(r.Context(), svcCtx)
resp, err := l.CancelResourceSpecAlarm(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -0,0 +1,24 @@
package core
import (
"github.com/zeromicro/go-zero/rest/httpx"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/logic/core"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/repository/result"
"net/http"
)
func DeleteResourceSpecHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.DeletePathId
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
l := core.NewDeleteResourceSpecLogic(r.Context(), svcCtx)
resp, err := l.DeleteResourceSpec(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -0,0 +1,24 @@
package core
import (
"github.com/zeromicro/go-zero/rest/httpx"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/logic/core"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/repository/result"
"net/http"
)
func DetailResourceSpecHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.IdReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
l := core.NewDetailResourceSpecLogic(r.Context(), svcCtx)
resp, err := l.DetailResourceSpec(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -0,0 +1,24 @@
package core
import (
"github.com/zeromicro/go-zero/rest/httpx"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/logic/core"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/repository/result"
"net/http"
)
func EditResourceSpecHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.ResourceSpec
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
l := core.NewEditResourceSpecLogic(r.Context(), svcCtx)
resp, err := l.EditResourceSpec(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -0,0 +1,24 @@
package core
import (
"github.com/zeromicro/go-zero/rest/httpx"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/logic/core"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/repository/result"
"net/http"
)
func GetClusterResourceSpecHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.ResourceSpecReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
l := core.NewGetClusterResourceSpecLogic(r.Context(), svcCtx)
resp, err := l.GetClusterResourceSpec(&req)
result.HttpResult(r, w, resp, err)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
package core
import (
"context"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type CancelResourceSpecAlarmLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCancelResourceSpecAlarmLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CancelResourceSpecAlarmLogic {
return &CancelResourceSpecAlarmLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *CancelResourceSpecAlarmLogic) CancelResourceSpecAlarm(req *types.IdReq) (resp *types.CommonResp, err error) {
db := l.svcCtx.DbEngin.Model(&types.ResourceSpec{}).Table("t_resource_spec")
err = db.Where("t_resource_spec.deleted_at is null and t_resource_spec.id = ?", req.Id).Update("change_type", 0).Error
if err != nil {
return nil, err
}
return
}

View File

@ -0,0 +1,35 @@
package core
import (
"context"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type DeleteResourceSpecLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewDeleteResourceSpecLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteResourceSpecLogic {
return &DeleteResourceSpecLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *DeleteResourceSpecLogic) DeleteResourceSpec(req *types.DeletePathId) (resp *types.CommonResp, err error) {
db := l.svcCtx.DbEngin.Model(&models.TResourceSpec{}).Table("t_resource_spec")
err = db.Delete(&models.TResourceSpec{}, req.Id).Error
if err != nil {
return nil, err
}
return
}

View File

@ -0,0 +1,47 @@
package core
import (
"context"
"github.com/pkg/errors"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type DetailResourceSpecLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewDetailResourceSpecLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DetailResourceSpecLogic {
return &DetailResourceSpecLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *DetailResourceSpecLogic) DetailResourceSpec(req *types.IdReq) (resp *types.ResourceSpec, err error) {
resp = &types.ResourceSpec{}
db := l.svcCtx.DbEngin.Model(&types.ResourceSpec{}).Table("t_resource_spec")
err = db.Where("id = ? and deleted_at is null", req.Id).Scan(&resp).Error
if err != nil {
return nil, err
}
if resp.Id == 0 {
logx.Errorf("resource spec not found , id:%s not found", req.Id)
return resp, errors.New("resource spec not found")
}
var baseSpecs []types.BaseResourceSpec
baseDb := l.svcCtx.DbEngin.Model(&types.BaseResourceSpec{}).Table("t_base_resource_spec")
baseDb = baseDb.Where("t_base_resource_spec.deleted_at is null and t_base_resource_spec.resource_spec_id = ?", resp.Id)
err = baseDb.Scan(&baseSpecs).Error
if err != nil {
return resp, err
}
resp.BaseResourceSpecs = baseSpecs
return
}

View File

@ -0,0 +1,54 @@
package core
import (
"context"
"github.com/pkg/errors"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type EditResourceSpecLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewEditResourceSpecLogic(ctx context.Context, svcCtx *svc.ServiceContext) *EditResourceSpecLogic {
return &EditResourceSpecLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *EditResourceSpecLogic) EditResourceSpec(req *types.ResourceSpec) (resp *types.CommonResp, err error) {
//检查是否存在
var count int64
db := l.svcCtx.DbEngin.Model(&types.ResourceSpec{}).Table("t_resource_spec")
err = db.Where("id = ? and deleted_at is null", req.Id).Count(&count).Error
if err != nil {
return nil, err
}
if count == 0 {
return nil, errors.New("资源规格不存在")
}
resp = &types.CommonResp{}
db = l.svcCtx.DbEngin.Model(&types.ResourceSpec{}).Table("t_resource_spec")
err = db.Where("id = ?", req.Id).Save(req).Error
if err != nil {
return nil, err
}
baseDb := l.svcCtx.DbEngin.Model(models.TBaseResourceSpec{}).Table("t_base_resource_spec")
for _, spec := range req.BaseResourceSpecs {
err = baseDb.Where("id = ?", spec.Id).Updates(&spec).Error
if err != nil {
return nil, err
}
}
return resp, nil
}

View File

@ -0,0 +1,405 @@
package core
import (
"context"
"errors"
"fmt"
"github.com/mitchellh/mapstructure"
"github.com/rs/zerolog/log"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/logic/schedule"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/utils"
"time"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
)
type GetClusterResourceSpecLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
const (
ChangeTypeCreated = 0
ChangeTypeModified = 1
ChangeTypeDeleted = 2
)
type APIResponse struct {
ClusterId string `json:"ClusterId"`
ClusterType string `json:"clusterType"`
Region string `json:"region"`
Resources []Resource `json:"resources"`
Msg string `json:"msg"`
}
type Resource struct {
Resource ResourceDetail `json:"resource"`
BaseResources []ResourceDetail `json:"baseResources"`
}
type ResourceDetail struct {
Type string `json:"type"`
Name string `json:"name"`
Total Metric `json:"total"`
Available Metric `json:"available"`
}
type Metric struct {
Unit string `json:"unit"`
Value float64 `json:"value"`
}
func NewGetClusterResourceSpecLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetClusterResourceSpecLogic {
return &GetClusterResourceSpecLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetClusterResourceSpecLogic) GetClusterResourceSpec(req *types.ResourceSpecReq) (*types.PageResult, error) {
if req.ClusterId == "" {
return nil, errors.New("ClusterId is required")
}
// 获取集群资源数据
startTime := time.Now()
apiResources, err := l.fetchClusterResources(req.ClusterId)
log.Debug().Msgf("调用获取ai训练资源接口耗时 %v", time.Since(startTime))
if err != nil {
return nil, fmt.Errorf("failed to fetch cluster resources: %w", err)
}
// 同步资源到数据库
if err := l.syncResourcesToDB(apiResources); err != nil {
return nil, fmt.Errorf("failed to sync resources: %w", err)
}
// 查询数据库结果
return l.queryDatabaseResults(req)
}
func (l *GetClusterResourceSpecLogic) fetchClusterResources(ClusterId string) ([]APIResponse, error) {
queryLogic := schedule.NewQueryResourcesLogic(l.ctx, l.svcCtx)
resources, err := queryLogic.QueryResources(&types.QueryResourcesReq{
ClusterIDs: []string{ClusterId},
})
if err != nil {
return nil, fmt.Errorf("query resources failed: %w", err)
}
var apiResponses []APIResponse
if err := l.decodeAPIResponse(resources.Data, &apiResponses); err != nil {
return nil, fmt.Errorf("decode response failed: %w", err)
}
return apiResponses, nil
}
func (l *GetClusterResourceSpecLogic) decodeAPIResponse(input interface{}, output *[]APIResponse) error {
config := &mapstructure.DecoderConfig{
Result: output,
TagName: "json",
ErrorUnused: true,
DecodeHook: mapstructure.ComposeDecodeHookFunc(
mapstructure.StringToTimeHookFunc(time.RFC3339),
mapstructure.StringToSliceHookFunc(","),
),
}
decoder, err := mapstructure.NewDecoder(config)
if err != nil {
return fmt.Errorf("failed to create decoder: %w", err)
}
if err := decoder.Decode(input); err != nil {
return fmt.Errorf("decoding error: %w", err)
}
return nil
}
func (l *GetClusterResourceSpecLogic) syncResourcesToDB(apiResponses []APIResponse) error {
for _, response := range apiResponses {
// 转换API响应到数据库模型
dbSpecs, apiSpecs, err := l.processAPIResponse(response)
if err != nil {
return err
}
// 处理资源变更
if err := l.handleResourceChanges(utils.StringToInt64(response.ClusterId), dbSpecs, apiSpecs); err != nil {
return fmt.Errorf("failed to handle resource changes: %w", err)
}
}
return nil
}
func (l *GetClusterResourceSpecLogic) processAPIResponse(response APIResponse) ([]models.TResourceSpec, []models.TResourceSpec, error) {
ClusterId := utils.StringToInt64(response.ClusterId)
var dbSpecs []models.TResourceSpec
if err := l.svcCtx.DbEngin.Model(models.TResourceSpec{}).Preload("BaseResourceSpecs").
Where("cluster_id = ?", ClusterId).
Find(&dbSpecs).Error; err != nil {
return nil, nil, fmt.Errorf("database query failed: %w", err)
}
var apiSpecs []models.TResourceSpec
for _, res := range response.Resources {
spec := l.convertToResourceSpec(ClusterId, res)
apiSpecs = append(apiSpecs, spec)
}
return dbSpecs, apiSpecs, nil
}
func (l *GetClusterResourceSpecLogic) handleResourceChanges(ClusterId int64, dbSpecs, apiSpecs []models.TResourceSpec) error {
// 创建资源映射
dbMap := make(map[string]models.TResourceSpec)
for _, spec := range dbSpecs {
key := resourceKey(spec.Type, spec.Name)
dbMap[key] = spec
}
apiMap := make(map[string]models.TResourceSpec)
for _, spec := range apiSpecs {
key := resourceKey(spec.Type, spec.Name)
apiMap[key] = spec
}
// 处理新增或更新的资源
for key, apiSpec := range apiMap {
dbSpec, exists := dbMap[key]
if !exists {
if err := l.createNewResource(&apiSpec); err != nil {
return err
}
continue
}
if l.isSpecChanged(dbSpec, apiSpec) {
if err := l.updateResource(&dbSpec, apiSpec); err != nil {
return err
}
}
}
// 处理删除的资源
for key, dbSpec := range dbMap {
if _, exists := apiMap[key]; !exists {
if err := l.markResourceDeleted(dbSpec.Id); err != nil {
return err
}
}
}
return nil
}
func resourceKey(resType, name string) string {
return fmt.Sprintf("%s::%s", resType, name)
}
func (l *GetClusterResourceSpecLogic) createNewResource(spec *models.TResourceSpec) error {
return l.svcCtx.DbEngin.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(spec).Error; err != nil {
return fmt.Errorf("failed to create resource: %w", err)
}
for i := range spec.BaseResourceSpecs {
spec.BaseResourceSpecs[i].ResourceSpecId = spec.Id
spec.BaseResourceSpecs[i].Id = 0
}
if len(spec.BaseResourceSpecs) > 0 {
if err := tx.CreateInBatches(spec.BaseResourceSpecs, 100).Error; err != nil {
return fmt.Errorf("failed to create base resources: %w", err)
}
}
return nil
})
}
func (l *GetClusterResourceSpecLogic) updateResource(existing *models.TResourceSpec, newSpec models.TResourceSpec) error {
return l.svcCtx.DbEngin.Transaction(func(tx *gorm.DB) error {
updates := map[string]interface{}{
"total_count": newSpec.TotalCount,
"available_count": newSpec.AvailableCount,
"change_type": ChangeTypeModified,
"update_time": time.Now(),
}
if err := tx.Model(existing).Updates(updates).Error; err != nil {
return fmt.Errorf("failed to update resource: %w", err)
}
return l.syncBaseResources(tx, existing.Id, newSpec.BaseResourceSpecs)
})
}
func (l *GetClusterResourceSpecLogic) syncBaseResources(tx *gorm.DB, specID int64, newResources []models.TBaseResourceSpec) error {
// 处理基础资源更新
var existingResources []models.TBaseResourceSpec
if err := tx.Where("resource_spec_id = ?", specID).Find(&existingResources).Error; err != nil {
return fmt.Errorf("failed to query base resources: %w", err)
}
existingMap := make(map[string]models.TBaseResourceSpec)
for _, r := range existingResources {
key := resourceKey(r.Type, r.Name)
existingMap[key] = r
}
// 处理更新和新增
for i, newRes := range newResources {
newRes.ResourceSpecId = specID
key := resourceKey(newRes.Type, newRes.Name)
if existing, exists := existingMap[key]; exists {
newRes.Id = existing.Id
newRes.CreateTime = existing.CreateTime
if err := tx.Save(&newRes).Error; err != nil {
return fmt.Errorf("failed to update base resource: %w", err)
}
} else {
if err := tx.Create(&newRes).Error; err != nil {
return fmt.Errorf("failed to create base resource: %w", err)
}
}
newResources[i] = newRes
}
// 处理删除
currentIDs := make(map[int64]struct{})
for _, r := range newResources {
currentIDs[r.Id] = struct{}{}
}
for _, existing := range existingResources {
if _, exists := currentIDs[existing.Id]; !exists {
if err := tx.Delete(&existing).Error; err != nil {
return fmt.Errorf("failed to delete base resource: %w", err)
}
}
}
return nil
}
func (l *GetClusterResourceSpecLogic) markResourceDeleted(id int64) error {
return l.svcCtx.DbEngin.Model(&models.TResourceSpec{}).
Where("id = ?", id).
Update("change_type", ChangeTypeDeleted).
Error
}
func (l *GetClusterResourceSpecLogic) isSpecChanged(old, new models.TResourceSpec) bool {
if old.TotalCount != new.TotalCount ||
old.AvailableCount != new.AvailableCount ||
old.Region != new.Region {
return true
}
// 比较基础资源
oldBaseMap := make(map[string]models.TBaseResourceSpec)
for _, br := range old.BaseResourceSpecs {
oldBaseMap[resourceKey(br.Type, br.Name)] = br
}
for _, newBr := range new.BaseResourceSpecs {
key := resourceKey(newBr.Type, newBr.Name)
oldBr, exists := oldBaseMap[key]
if !exists ||
oldBr.TotalValue != newBr.TotalValue ||
oldBr.AvailableValue != newBr.AvailableValue {
return true
}
delete(oldBaseMap, key)
}
return len(oldBaseMap) > 0
}
func (l *GetClusterResourceSpecLogic) convertToResourceSpec(ClusterId int64, res Resource) models.TResourceSpec {
spec := models.TResourceSpec{
Type: res.Resource.Type,
Name: res.Resource.Name,
TotalCount: int64(res.Resource.Total.Value),
AvailableCount: int64(res.Resource.Available.Value),
ClusterId: ClusterId,
CreateTime: time.Now(),
UpdateTime: time.Now(),
ChangeType: ChangeTypeCreated,
}
for _, br := range res.BaseResources {
spec.BaseResourceSpecs = append(spec.BaseResourceSpecs, models.TBaseResourceSpec{
Type: br.Type,
Name: br.Name,
TotalValue: br.Total.Value,
TotalUnit: br.Total.Unit,
AvailableValue: br.Available.Value,
AvailableUnit: br.Available.Unit,
CreateTime: time.Now(),
UpdateTime: time.Now(),
})
}
return spec
}
func (l *GetClusterResourceSpecLogic) queryDatabaseResults(req *types.ResourceSpecReq) (*types.PageResult, error) {
result := &types.PageResult{
PageNum: req.PageNum,
PageSize: req.PageSize,
}
query := l.buildBaseQuery(req)
if err := query.Count(&result.Total).Error; err != nil {
return nil, fmt.Errorf("failed to count records: %w", err)
}
var specs []*models.TResourceSpec
if err := query.Model(models.TResourceSpec{}).Preload("BaseResourceSpecs").
Scopes(paginate(req.PageNum, req.PageSize)).
Find(&specs).Error; err != nil {
return nil, fmt.Errorf("failed to query resources: %w", err)
}
result.List = specs
return result, nil
}
func (l *GetClusterResourceSpecLogic) buildBaseQuery(req *types.ResourceSpecReq) *gorm.DB {
query := l.svcCtx.DbEngin.Model(&models.TResourceSpec{}).
Where("cluster_id = ?", utils.StringToInt64(req.ClusterId)).
Where("deleted_at IS NULL")
if req.Status != "" {
query = query.Where("status = ?", req.Status)
}
if req.ChangeType != "" {
query = query.Where("change_type = ?", req.ChangeType)
}
if req.Type != "" {
query = query.Where("type = ?", req.Type)
}
if req.Name != "" {
query = query.Where("name LIKE ?", "%"+req.Name+"%")
}
return query
}
func paginate(pageNum, pageSize int) func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
offset := (pageNum - 1) * pageSize
return db.Offset(offset).Limit(pageSize).Order("create_time DESC")
}
}

View File

@ -3,6 +3,7 @@ package jcs
import (
"encoding/json"
"fmt"
"github.com/rs/zerolog/log"
"github.com/zeromicro/go-zero/core/logx"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/database"
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
@ -54,7 +55,7 @@ func StatusReport(url string, report interface{}) error {
logx.Errorf("############ Report Status Message After Sending %s", string(rp.Body()))
return fmt.Errorf("report status message failed: %s", resp.Msg)
}
logx.Errorf("############ Report Status Message After Sending %s", string(rp.Body()))
log.Debug().Msgf("任务状态上报到中间件返回: [%v]", string(rp.Body()))
return nil
}

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@ type (
InstanceClass string `db:"instance_class" json:"instanceClass"` // 实例类别
InstanceClassChinese string `db:"instance_class_chinese" json:"instanceClassChinese"` // 实例类别中文描述
Description string `db:"description" json:"description"` // 描述
Status int64 `db:"status" json:"status"` // 状态状态 0-不可用1-可用
Version string `db:"version" json:"version"` // 版本
CreatedAt time.Time `db:"created_at" json:"createdAt"` // 创建时间
UpdatedAt time.Time `db:"updated_at" json:"updatedAt"` // 更新时间

View File

@ -0,0 +1,29 @@
package models
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var _ TBaseResourceSpecModel = (*customTBaseResourceSpecModel)(nil)
type (
// TBaseResourceSpecModel is an interface to be customized, add more methods here,
// and implement the added methods in customTBaseResourceSpecModel.
TBaseResourceSpecModel interface {
tBaseResourceSpecModel
withSession(session sqlx.Session) TBaseResourceSpecModel
}
customTBaseResourceSpecModel struct {
*defaultTBaseResourceSpecModel
}
)
// NewTBaseResourceSpecModel returns a model for the database table.
func NewTBaseResourceSpecModel(conn sqlx.SqlConn) TBaseResourceSpecModel {
return &customTBaseResourceSpecModel{
defaultTBaseResourceSpecModel: newTBaseResourceSpecModel(conn),
}
}
func (m *customTBaseResourceSpecModel) withSession(session sqlx.Session) TBaseResourceSpecModel {
return NewTBaseResourceSpecModel(sqlx.NewSqlConnFromSession(session))
}

View File

@ -0,0 +1,97 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.8.1
package models
import (
"context"
"database/sql"
"fmt"
"gorm.io/gorm"
"strings"
"time"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
tBaseResourceSpecFieldNames = builder.RawFieldNames(&TBaseResourceSpec{})
tBaseResourceSpecRows = strings.Join(tBaseResourceSpecFieldNames, ",")
tBaseResourceSpecRowsExpectAutoSet = strings.Join(stringx.Remove(tBaseResourceSpecFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
tBaseResourceSpecRowsWithPlaceHolder = strings.Join(stringx.Remove(tBaseResourceSpecFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
tBaseResourceSpecModel interface {
Insert(ctx context.Context, data *TBaseResourceSpec) (sql.Result, error)
FindOne(ctx context.Context, id int64) (*TBaseResourceSpec, error)
Update(ctx context.Context, data *TBaseResourceSpec) error
Delete(ctx context.Context, id int64) error
}
defaultTBaseResourceSpecModel struct {
conn sqlx.SqlConn
table string
}
TBaseResourceSpec struct {
Id int64 `db:"id" json:"id,omitempty"` // 主键id
ResourceSpecId int64 `db:"resource_spec_id" json:"resourceSpecId,omitempty"` // 关联资源规格ID
Type string `db:"type" json:"type,omitempty"` // 类型名称
Name string `db:"name" json:"name,omitempty"` // 名称(如显存类型)
TotalValue float64 `db:"total_value" json:"totalValue,omitempty"` // 总量值
TotalUnit string `db:"total_unit" json:"totalUnit,omitempty"` // 总量值单位GB/core等
AvailableValue float64 `db:"available_value" json:"availableValue,omitempty"` // 可用值
AvailableUnit string `db:"available_unit" json:"availableUnit,omitempty"` // 可用值单位GB/core等
UserId int64 `db:"user_id" json:"userId"` // 用户ID
CreateTime time.Time `db:"create_time" json:"createTime"` // 创建时间
UpdateTime time.Time `db:"update_time" json:"updateTime"` // 更新时间
DeletedAt gorm.DeletedAt `db:"deleted_at" json:"-"` // 删除时间
}
)
func newTBaseResourceSpecModel(conn sqlx.SqlConn) *defaultTBaseResourceSpecModel {
return &defaultTBaseResourceSpecModel{
conn: conn,
table: "`t_base_resource_spec`",
}
}
func (m *defaultTBaseResourceSpecModel) Delete(ctx context.Context, id int64) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultTBaseResourceSpecModel) FindOne(ctx context.Context, id int64) (*TBaseResourceSpec, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", tBaseResourceSpecRows, m.table)
var resp TBaseResourceSpec
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultTBaseResourceSpecModel) Insert(ctx context.Context, data *TBaseResourceSpec) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, tBaseResourceSpecRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.ResourceSpecId, data.Type, data.Name, data.TotalValue, data.TotalUnit, data.AvailableValue, data.AvailableUnit, data.UserId, data.DeletedAt)
return ret, err
}
func (m *defaultTBaseResourceSpecModel) Update(ctx context.Context, data *TBaseResourceSpec) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, tBaseResourceSpecRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.ResourceSpecId, data.Type, data.Name, data.TotalValue, data.TotalUnit, data.AvailableValue, data.AvailableUnit, data.UserId, data.DeletedAt, data.Id)
return err
}
func (m *defaultTBaseResourceSpecModel) tableName() string {
return m.table
}

View File

@ -0,0 +1,29 @@
package models
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var _ TResourceSpecModel = (*customTResourceSpecModel)(nil)
type (
// TResourceSpecModel is an interface to be customized, add more methods here,
// and implement the added methods in customTResourceSpecModel.
TResourceSpecModel interface {
tResourceSpecModel
withSession(session sqlx.Session) TResourceSpecModel
}
customTResourceSpecModel struct {
*defaultTResourceSpecModel
}
)
// NewTResourceSpecModel returns a model for the database table.
func NewTResourceSpecModel(conn sqlx.SqlConn) TResourceSpecModel {
return &customTResourceSpecModel{
defaultTResourceSpecModel: newTResourceSpecModel(conn),
}
}
func (m *customTResourceSpecModel) withSession(session sqlx.Session) TResourceSpecModel {
return NewTResourceSpecModel(sqlx.NewSqlConnFromSession(session))
}

View File

@ -0,0 +1,102 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.8.1
package models
import (
"context"
"database/sql"
"fmt"
"gorm.io/gorm"
"strings"
"time"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
tResourceSpecFieldNames = builder.RawFieldNames(&TResourceSpec{})
tResourceSpecRows = strings.Join(tResourceSpecFieldNames, ",")
tResourceSpecRowsExpectAutoSet = strings.Join(stringx.Remove(tResourceSpecFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
tResourceSpecRowsWithPlaceHolder = strings.Join(stringx.Remove(tResourceSpecFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
tResourceSpecModel interface {
Insert(ctx context.Context, data *TResourceSpec) (sql.Result, error)
FindOne(ctx context.Context, id int64) (*TResourceSpec, error)
Update(ctx context.Context, data *TResourceSpec) error
Delete(ctx context.Context, id int64) error
}
defaultTResourceSpecModel struct {
conn sqlx.SqlConn
table string
}
TResourceSpec struct {
Id int64 `db:"id" json:"id,omitempty"` // 主键id
Type string `db:"type" json:"type,omitempty"` // 类型名称
Name string `db:"name" json:"name,omitempty"` // 规格名称
TotalCount int64 `db:"total_count" json:"totalCount,omitempty"` // 资源总量
AvailableCount int64 `db:"available_count" json:"availableCount,omitempty"` // 可用数量
ChangeType int64 `db:"change_type" json:"changeType,omitempty"` // 变更类型0: 正常1变更2删除
Status int64 `db:"status" json:"status,omitempty"` // 状态0未上架1已上架
Region string `db:"region" json:"region,omitempty"` // 所属区域(可扩展多区域)
ClusterId int64 `db:"cluster_id" json:"clusterId,string,omitempty"` // 集群ID
CostPerUnit float64 `db:"cost_per_unit" json:"costPerUnit,omitempty"` // 单位时间积分消耗
CostType string `db:"cost_type" json:"costType,omitempty"` // 计费类型hourly, daily, monthly,perUse
UserId int64 `db:"user_id" json:"userId"` // 用户ID
CreateTime time.Time `db:"create_time" json:"createTime"` // 创建时间
UpdateTime time.Time `db:"update_time" json:"updateTime"` // 更新时间
DeletedAt gorm.DeletedAt `db:"deleted_at" json:"-"` // 删除时间
BaseResourceSpecs []TBaseResourceSpec `gorm:"foreignKey:ResourceSpecId" json:"baseResourceSpecs,omitempty"`
}
)
func newTResourceSpecModel(conn sqlx.SqlConn) *defaultTResourceSpecModel {
return &defaultTResourceSpecModel{
conn: conn,
table: "`t_resource_spec`",
}
}
func (m *defaultTResourceSpecModel) Delete(ctx context.Context, id int64) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultTResourceSpecModel) FindOne(ctx context.Context, id int64) (*TResourceSpec, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", tResourceSpecRows, m.table)
var resp TResourceSpec
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultTResourceSpecModel) Insert(ctx context.Context, data *TResourceSpec) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, tResourceSpecRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Type, data.Name, data.TotalCount, data.AvailableCount, data.ChangeType, data.Status, data.Region, data.ClusterId, data.UserId, data.DeletedAt)
return ret, err
}
func (m *defaultTResourceSpecModel) Update(ctx context.Context, data *TResourceSpec) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, tResourceSpecRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.Type, data.Name, data.TotalCount, data.AvailableCount, data.ChangeType, data.Status, data.Region, data.ClusterId, data.UserId, data.DeletedAt, data.Id)
return err
}
func (m *defaultTResourceSpecModel) tableName() string {
return m.table
}