Skip to content

Commit

Permalink
fix(dbm-services): 错误使用匹配符号 #8881
Browse files Browse the repository at this point in the history
  • Loading branch information
ymakedaq committed Jan 3, 2025
1 parent b18ceff commit cbd6811
Show file tree
Hide file tree
Showing 2 changed files with 213 additions and 24 deletions.
218 changes: 198 additions & 20 deletions dbm-services/common/db-resource/internal/svr/apply/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ package apply
import (
"fmt"
"path"
"slices"
"sort"
"strings"

"dbm-services/common/db-resource/internal/config"
Expand All @@ -32,14 +34,195 @@ import (
// SearchContext TODO
type SearchContext struct {
*ObjectDetail
RsType string
IntetionBkBizId int
IdcCitys []string
SpecialHostIds []int
RsType string
IntetionBkBizId int
IdcCitys []string
SpecialSubZoneIds []string
SpecialHostIds []int
}

// applyGroupsInSameLocaltion apply groups in same location
func applyGroupsInSameLocaltion(param RequestInputParam) (pickers []*PickerObject, err error) {
var picker *PickerObject
resourceReqList, err := param.SortDetails()
if err != nil {
logger.Error("对请求参数排序失败%v", err)
return nil, err
}
var idcCitys []string
v := resourceReqList[0]
idcCitys, err = getLogicIdcCitys(v)
if err != nil {
logger.Error("get logic citys failed %s", err.Error())
return pickers, err
}
// 根据请求,按照请求的分组,分别计算出每个分组的匹配的园区的优先级
groupcampusNice, err := getGroupcampusNice(param, resourceReqList, idcCitys)
if err != nil {
logger.Error("order campus nice failed %s", err.Error())
return pickers, err
}
// 因为整个大的分组在需要分配机器在同一个园区,这里合并所有的分组的园区优先级
// 合并之后再次排序,返回整体的园区优先级
subzoneIds := sortgroupcampusNice(groupcampusNice)
logger.Info("sort subzone ids %v", subzoneIds)
if len(subzoneIds) == 0 {
return pickers, errno.ErrResourceinsufficient.Add("没有符合条件的资源")
}
for _, subzoneId := range subzoneIds {
pickers = []*PickerObject{}
for _, v := range resourceReqList {
s := &SearchContext{
IntetionBkBizId: param.ForbizId,
RsType: param.ResourceType,
ObjectDetail: &v,
IdcCitys: idcCitys,
SpecialHostIds: v.Hosts.GetBkHostIds(),
SpecialSubZoneIds: []string{subzoneId},
}
if err = s.PickCheck(); err != nil {
logger.Error("挑选资源失败:%v", err)
goto RollBack
}
// 挑选符合需求的资源
picker, err = s.PickInstance()
if err != nil {
logger.Error("挑选资源失败:%v", err)
goto RollBack
}
// Debug Print Log 挑选实例分区的情况
picker.DebugDistrubuteLog()
// 更新挑选到的资源的状态为Preselected
if updateErr := picker.PreselectedSatisfiedInstance(); updateErr != nil {
goto RollBack
}
// 追加到挑选好的分组
pickers = append(pickers, picker)
}
return pickers, nil
RollBack:
RollBackAllInstanceUnused(pickers)
}
return pickers, err
}
func getGroupcampusNice(param RequestInputParam, resourceReqList []ObjectDetail,
idcCitys []string) (groupcampusNice map[string]map[string]*SubZoneSummary,
err error) {
groupcampusNice = make(map[string]map[string]*SubZoneSummary)
for _, v := range resourceReqList {
s := &SearchContext{
IntetionBkBizId: param.ForbizId,
RsType: param.ResourceType,
ObjectDetail: &v,
IdcCitys: idcCitys,
SpecialHostIds: v.Hosts.GetBkHostIds(),
}
var items []model.TbRpDetail
db := model.DB.Self.Table(model.TbRpDetailName())
s.pickBase(db)
if err = db.Scan(&items).Error; err != nil {
logger.Error("query failed %s", err.Error())
return nil, errno.ErrDBQuery.AddErr(err)
}
campusSummarys := make(map[string]*SubZoneSummary)
for _, item := range items {
if _, ok := campusSummarys[item.SubZoneID]; !ok {
campusSummarys[item.SubZoneID] = &SubZoneSummary{
Count: 1,
EquipmentIdList: []string{item.RackID},
LinkNetdeviceList: strings.Split(item.NetDeviceID, ","),
RequestCount: v.Count,
}
} else {
campusSummarys[item.SubZoneID].Count++
campusSummarys[item.SubZoneID].EquipmentIdList = append(campusSummarys[item.SubZoneID].EquipmentIdList, item.RackID)
campusSummarys[item.SubZoneID].LinkNetdeviceList = append(campusSummarys[item.SubZoneID].LinkNetdeviceList,
strings.Split(item.NetDeviceID, ",")...)
}
}
groupcampusNice[v.GroupMark] = campusSummarys
}
return groupcampusNice, nil
}

func sortgroupcampusNice(gpms map[string]map[string]*SubZoneSummary) []string {
subzones := []string{}
gcnsMap := make(map[string]*CampusNice)
var cns []CampusNice
for _, campuseSummary := range gpms {
for campus := range campuseSummary {
equipmentIdList := lo.Uniq(campuseSummary[campus].EquipmentIdList)
linkNetdeviceList := lo.Uniq(campuseSummary[campus].LinkNetdeviceList)
count := campuseSummary[campus].Count
requestCount := campuseSummary[campus].RequestCount
if count >= requestCount && len(equipmentIdList) >= requestCount &&
len(linkNetdeviceList) >= requestCount {
cns = append(cns, CampusNice{
Campus: campus,
Count: int64(count + len(equipmentIdList)*(1+PriorityP3) + len(linkNetdeviceList)*(PriorityP3+1)),
})
}
}
}

for _, cn := range cns {
if _, ok := gcnsMap[cn.Campus]; !ok {
gcnsMap[cn.Campus] = &CampusNice{
Campus: cn.Campus,
Count: cn.Count,
}
} else {
gcnsMap[cn.Campus].Count += cn.Count
}
}
var gcns []CampusNice
for key := range gcnsMap {
gcns = append(gcns, CampusNice{
Campus: key,
Count: gcnsMap[key].Count,
})
}
sort.Sort(CampusWrapper{gcns, func(p, q *CampusNice) bool {
return q.Count < p.Count
}})

for _, v := range gcns {
subzones = append(subzones, v.Campus)
}
return subzones
}

// SubZoneSummary subzone summary
type SubZoneSummary struct {
RequestCount int
Count int
EquipmentIdList []string // 存在的设备Id
LinkNetdeviceList []string // 存在的网卡Id
}

func getLogicIdcCitys(v ObjectDetail) (idcCitys []string, err error) {
if config.AppConfig.RunMode == "dev" {
idcCitys = []string{}
} else if cmutil.ElementNotInArry(v.Affinity, []string{CROSS_RACK, NONE}) ||
lo.IsNotEmpty(v.LocationSpec.City) ||
len(v.Hosts) > 0 {
idcCitys, err = dbmapi.GetIdcCityByLogicCity(v.LocationSpec.City)
if err != nil {
logger.Error("request real citys by logic city %s from bkdbm api failed:%v", v.LocationSpec.City, err)
return []string{}, err
}
}
return idcCitys, nil
}

// CycleApply 循环匹配
func CycleApply(param RequestInputParam) (pickers []*PickerObject, err error) {
// 多个请求参数分组在同一个地方
affinitys := lo.Uniq(param.GetAllAffinitys())
if param.GroupsInSameLocation && len(param.Details) > 1 && len(affinitys) == 1 &&
slices.Contains([]string{SAME_SUBZONE, SAME_SUBZONE_CROSS_SWTICH}, affinitys[0]) {
return applyGroupsInSameLocaltion(param)
}
resourceReqList, err := param.SortDetails()
if err != nil {
logger.Error("对请求参数排序失败%v", err)
Expand All @@ -52,19 +235,11 @@ func CycleApply(param RequestInputParam) (pickers []*PickerObject, err error) {
if v.Affinity == "" || v.Count <= 1 {
v.Affinity = NONE
}
var idcCitys []string
if config.AppConfig.RunMode == "dev" {
idcCitys = []string{}
} else if cmutil.ElementNotInArry(v.Affinity, []string{CROSS_RACK, NONE}) ||
lo.IsNotEmpty(v.LocationSpec.City) ||
len(v.Hosts) > 0 {
idcCitys, err = dbmapi.GetIdcCityByLogicCity(v.LocationSpec.City)
if err != nil {
logger.Error("request real citys by logic city %s from bkdbm api failed:%v", v.LocationSpec.City, err)
return pickers, err
}
idcCitys, err := getLogicIdcCitys(v)
if err != nil {
logger.Error("get logic citys failed %s", err.Error())
return pickers, err
}

s := &SearchContext{
IntetionBkBizId: param.ForbizId,
RsType: param.ResourceType,
Expand Down Expand Up @@ -270,7 +445,7 @@ func (o *SearchContext) MatchIntetionBkBiz(db *gorm.DB) {
// 如果没有指定专属业务,就表示只能选用公共的资源
// 不能匹配打了业务标签的资源
if o.IntetionBkBizId <= 0 {
db.Where("dedicated_biz == 0")
db.Where("dedicated_biz = 0")
} else {
db.Where("dedicated_biz in (?)", []int{0, o.IntetionBkBizId})
}
Expand All @@ -281,7 +456,7 @@ func (o *SearchContext) MatchRsType(db *gorm.DB) {
// 如果没有指定资源类型,表示只能选择无资源类型标签的资源
// 没有资源类型标签的资源可以被所有其他类型使用
if lo.IsEmpty(o.RsType) {
db.Where("rs_type == 'PUBLIC' ")
db.Where("rs_type = 'PUBLIC' ")
} else {
db.Where("rs_type in (?)", []string{"PUBLIC", o.RsType})
}
Expand Down Expand Up @@ -345,12 +520,15 @@ func (o *SearchContext) MatchLocationSpec(db *gorm.DB) {
db = db.Where("city = ? ", o.LocationSpec.City)
}
if o.LocationSpec.SubZoneIsEmpty() {
if len(o.SpecialSubZoneIds) > 0 {
db.Where("sub_zone_id in (?)", o.SpecialSubZoneIds)
}
return
}
if o.LocationSpec.IncludeOrExclude {
db.Where("sub_zone_id in ?", o.LocationSpec.SubZoneIds)
db.Where("sub_zone_id in (?)", o.LocationSpec.SubZoneIds)
} else {
db.Where("sub_zone_id not in ?", o.LocationSpec.SubZoneIds)
db.Where("sub_zone_id not in (?)", o.LocationSpec.SubZoneIds)
}
}

Expand Down
19 changes: 15 additions & 4 deletions dbm-services/common/db-resource/internal/svr/apply/apply_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,24 @@ type ActionInfo struct {

// RequestInputParam 请求接口参数
type RequestInputParam struct {
ResourceType string `json:"resource_type"` // 申请的资源用作的用途 Redis|MySQL|Proxy
DryRun bool `json:"dry_run"`
ForbizId int `json:"for_biz_id"`
Details []ObjectDetail `json:"details" binding:"required,gt=0,dive"`
ResourceType string `json:"resource_type"` // 申请的资源用作的用途 Redis|MySQL|Proxy
DryRun bool `json:"dry_run"`
ForbizId int `json:"for_biz_id"`
Details []ObjectDetail `json:"details" binding:"required,gt=0,dive"`
GroupsInSameLocation bool `json:"groups_in_same_location"`
ActionInfo
}

// GetAllAffinitys 获取这批请求的所有亲和性的参数
func (param RequestInputParam) GetAllAffinitys() (affinitys []string) {
for _, d := range param.Details {
if !lo.Contains(affinitys, d.Affinity) {
affinitys = append(affinitys, d.Affinity)
}
}
return affinitys
}

// BuildMessage build apply message
func (param RequestInputParam) BuildMessage() (msg string) {
var count int
Expand Down

0 comments on commit cbd6811

Please sign in to comment.