Skip to content

Commit 4928cea

Browse files
ymakedaqiSecloud
authored andcommitted
fix(dbm-services): 错误使用匹配符号 #8881
1 parent e808e3d commit 4928cea

File tree

2 files changed

+213
-24
lines changed

2 files changed

+213
-24
lines changed

dbm-services/common/db-resource/internal/svr/apply/apply.go

Lines changed: 198 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ package apply
1414
import (
1515
"fmt"
1616
"path"
17+
"slices"
18+
"sort"
1719
"strings"
1820

1921
"dbm-services/common/db-resource/internal/config"
@@ -32,14 +34,195 @@ import (
3234
// SearchContext TODO
3335
type SearchContext struct {
3436
*ObjectDetail
35-
RsType string
36-
IntetionBkBizId int
37-
IdcCitys []string
38-
SpecialHostIds []int
37+
RsType string
38+
IntetionBkBizId int
39+
IdcCitys []string
40+
SpecialSubZoneIds []string
41+
SpecialHostIds []int
42+
}
43+
44+
// applyGroupsInSameLocaltion apply groups in same location
45+
func applyGroupsInSameLocaltion(param RequestInputParam) (pickers []*PickerObject, err error) {
46+
var picker *PickerObject
47+
resourceReqList, err := param.SortDetails()
48+
if err != nil {
49+
logger.Error("对请求参数排序失败%v", err)
50+
return nil, err
51+
}
52+
var idcCitys []string
53+
v := resourceReqList[0]
54+
idcCitys, err = getLogicIdcCitys(v)
55+
if err != nil {
56+
logger.Error("get logic citys failed %s", err.Error())
57+
return pickers, err
58+
}
59+
// 根据请求,按照请求的分组,分别计算出每个分组的匹配的园区的优先级
60+
groupcampusNice, err := getGroupcampusNice(param, resourceReqList, idcCitys)
61+
if err != nil {
62+
logger.Error("order campus nice failed %s", err.Error())
63+
return pickers, err
64+
}
65+
// 因为整个大的分组在需要分配机器在同一个园区,这里合并所有的分组的园区优先级
66+
// 合并之后再次排序,返回整体的园区优先级
67+
subzoneIds := sortgroupcampusNice(groupcampusNice)
68+
logger.Info("sort subzone ids %v", subzoneIds)
69+
if len(subzoneIds) == 0 {
70+
return pickers, errno.ErrResourceinsufficient.Add("没有符合条件的资源")
71+
}
72+
for _, subzoneId := range subzoneIds {
73+
pickers = []*PickerObject{}
74+
for _, v := range resourceReqList {
75+
s := &SearchContext{
76+
IntetionBkBizId: param.ForbizId,
77+
RsType: param.ResourceType,
78+
ObjectDetail: &v,
79+
IdcCitys: idcCitys,
80+
SpecialHostIds: v.Hosts.GetBkHostIds(),
81+
SpecialSubZoneIds: []string{subzoneId},
82+
}
83+
if err = s.PickCheck(); err != nil {
84+
logger.Error("挑选资源失败:%v", err)
85+
goto RollBack
86+
}
87+
// 挑选符合需求的资源
88+
picker, err = s.PickInstance()
89+
if err != nil {
90+
logger.Error("挑选资源失败:%v", err)
91+
goto RollBack
92+
}
93+
// Debug Print Log 挑选实例分区的情况
94+
picker.DebugDistrubuteLog()
95+
// 更新挑选到的资源的状态为Preselected
96+
if updateErr := picker.PreselectedSatisfiedInstance(); updateErr != nil {
97+
goto RollBack
98+
}
99+
// 追加到挑选好的分组
100+
pickers = append(pickers, picker)
101+
}
102+
return pickers, nil
103+
RollBack:
104+
RollBackAllInstanceUnused(pickers)
105+
}
106+
return pickers, err
107+
}
108+
func getGroupcampusNice(param RequestInputParam, resourceReqList []ObjectDetail,
109+
idcCitys []string) (groupcampusNice map[string]map[string]*SubZoneSummary,
110+
err error) {
111+
groupcampusNice = make(map[string]map[string]*SubZoneSummary)
112+
for _, v := range resourceReqList {
113+
s := &SearchContext{
114+
IntetionBkBizId: param.ForbizId,
115+
RsType: param.ResourceType,
116+
ObjectDetail: &v,
117+
IdcCitys: idcCitys,
118+
SpecialHostIds: v.Hosts.GetBkHostIds(),
119+
}
120+
var items []model.TbRpDetail
121+
db := model.DB.Self.Table(model.TbRpDetailName())
122+
s.pickBase(db)
123+
if err = db.Scan(&items).Error; err != nil {
124+
logger.Error("query failed %s", err.Error())
125+
return nil, errno.ErrDBQuery.AddErr(err)
126+
}
127+
campusSummarys := make(map[string]*SubZoneSummary)
128+
for _, item := range items {
129+
if _, ok := campusSummarys[item.SubZoneID]; !ok {
130+
campusSummarys[item.SubZoneID] = &SubZoneSummary{
131+
Count: 1,
132+
EquipmentIdList: []string{item.RackID},
133+
LinkNetdeviceList: strings.Split(item.NetDeviceID, ","),
134+
RequestCount: v.Count,
135+
}
136+
} else {
137+
campusSummarys[item.SubZoneID].Count++
138+
campusSummarys[item.SubZoneID].EquipmentIdList = append(campusSummarys[item.SubZoneID].EquipmentIdList, item.RackID)
139+
campusSummarys[item.SubZoneID].LinkNetdeviceList = append(campusSummarys[item.SubZoneID].LinkNetdeviceList,
140+
strings.Split(item.NetDeviceID, ",")...)
141+
}
142+
}
143+
groupcampusNice[v.GroupMark] = campusSummarys
144+
}
145+
return groupcampusNice, nil
146+
}
147+
148+
func sortgroupcampusNice(gpms map[string]map[string]*SubZoneSummary) []string {
149+
subzones := []string{}
150+
gcnsMap := make(map[string]*CampusNice)
151+
var cns []CampusNice
152+
for _, campuseSummary := range gpms {
153+
for campus := range campuseSummary {
154+
equipmentIdList := lo.Uniq(campuseSummary[campus].EquipmentIdList)
155+
linkNetdeviceList := lo.Uniq(campuseSummary[campus].LinkNetdeviceList)
156+
count := campuseSummary[campus].Count
157+
requestCount := campuseSummary[campus].RequestCount
158+
if count >= requestCount && len(equipmentIdList) >= requestCount &&
159+
len(linkNetdeviceList) >= requestCount {
160+
cns = append(cns, CampusNice{
161+
Campus: campus,
162+
Count: int64(count + len(equipmentIdList)*(1+PriorityP3) + len(linkNetdeviceList)*(PriorityP3+1)),
163+
})
164+
}
165+
}
166+
}
167+
168+
for _, cn := range cns {
169+
if _, ok := gcnsMap[cn.Campus]; !ok {
170+
gcnsMap[cn.Campus] = &CampusNice{
171+
Campus: cn.Campus,
172+
Count: cn.Count,
173+
}
174+
} else {
175+
gcnsMap[cn.Campus].Count += cn.Count
176+
}
177+
}
178+
var gcns []CampusNice
179+
for key := range gcnsMap {
180+
gcns = append(gcns, CampusNice{
181+
Campus: key,
182+
Count: gcnsMap[key].Count,
183+
})
184+
}
185+
sort.Sort(CampusWrapper{gcns, func(p, q *CampusNice) bool {
186+
return q.Count < p.Count
187+
}})
188+
189+
for _, v := range gcns {
190+
subzones = append(subzones, v.Campus)
191+
}
192+
return subzones
193+
}
194+
195+
// SubZoneSummary subzone summary
196+
type SubZoneSummary struct {
197+
RequestCount int
198+
Count int
199+
EquipmentIdList []string // 存在的设备Id
200+
LinkNetdeviceList []string // 存在的网卡Id
201+
}
202+
203+
func getLogicIdcCitys(v ObjectDetail) (idcCitys []string, err error) {
204+
if config.AppConfig.RunMode == "dev" {
205+
idcCitys = []string{}
206+
} else if cmutil.ElementNotInArry(v.Affinity, []string{CROSS_RACK, NONE}) ||
207+
lo.IsNotEmpty(v.LocationSpec.City) ||
208+
len(v.Hosts) > 0 {
209+
idcCitys, err = dbmapi.GetIdcCityByLogicCity(v.LocationSpec.City)
210+
if err != nil {
211+
logger.Error("request real citys by logic city %s from bkdbm api failed:%v", v.LocationSpec.City, err)
212+
return []string{}, err
213+
}
214+
}
215+
return idcCitys, nil
39216
}
40217

41218
// CycleApply 循环匹配
42219
func CycleApply(param RequestInputParam) (pickers []*PickerObject, err error) {
220+
// 多个请求参数分组在同一个地方
221+
affinitys := lo.Uniq(param.GetAllAffinitys())
222+
if param.GroupsInSameLocation && len(param.Details) > 1 && len(affinitys) == 1 &&
223+
slices.Contains([]string{SAME_SUBZONE, SAME_SUBZONE_CROSS_SWTICH}, affinitys[0]) {
224+
return applyGroupsInSameLocaltion(param)
225+
}
43226
resourceReqList, err := param.SortDetails()
44227
if err != nil {
45228
logger.Error("对请求参数排序失败%v", err)
@@ -52,19 +235,11 @@ func CycleApply(param RequestInputParam) (pickers []*PickerObject, err error) {
52235
if v.Affinity == "" || v.Count <= 1 {
53236
v.Affinity = NONE
54237
}
55-
var idcCitys []string
56-
if config.AppConfig.RunMode == "dev" {
57-
idcCitys = []string{}
58-
} else if cmutil.ElementNotInArry(v.Affinity, []string{CROSS_RACK, NONE}) ||
59-
lo.IsNotEmpty(v.LocationSpec.City) ||
60-
len(v.Hosts) > 0 {
61-
idcCitys, err = dbmapi.GetIdcCityByLogicCity(v.LocationSpec.City)
62-
if err != nil {
63-
logger.Error("request real citys by logic city %s from bkdbm api failed:%v", v.LocationSpec.City, err)
64-
return pickers, err
65-
}
238+
idcCitys, err := getLogicIdcCitys(v)
239+
if err != nil {
240+
logger.Error("get logic citys failed %s", err.Error())
241+
return pickers, err
66242
}
67-
68243
s := &SearchContext{
69244
IntetionBkBizId: param.ForbizId,
70245
RsType: param.ResourceType,
@@ -270,7 +445,7 @@ func (o *SearchContext) MatchIntetionBkBiz(db *gorm.DB) {
270445
// 如果没有指定专属业务,就表示只能选用公共的资源
271446
// 不能匹配打了业务标签的资源
272447
if o.IntetionBkBizId <= 0 {
273-
db.Where("dedicated_biz == 0")
448+
db.Where("dedicated_biz = 0")
274449
} else {
275450
db.Where("dedicated_biz in (?)", []int{0, o.IntetionBkBizId})
276451
}
@@ -281,7 +456,7 @@ func (o *SearchContext) MatchRsType(db *gorm.DB) {
281456
// 如果没有指定资源类型,表示只能选择无资源类型标签的资源
282457
// 没有资源类型标签的资源可以被所有其他类型使用
283458
if lo.IsEmpty(o.RsType) {
284-
db.Where("rs_type == 'PUBLIC' ")
459+
db.Where("rs_type = 'PUBLIC' ")
285460
} else {
286461
db.Where("rs_type in (?)", []string{"PUBLIC", o.RsType})
287462
}
@@ -345,12 +520,15 @@ func (o *SearchContext) MatchLocationSpec(db *gorm.DB) {
345520
db = db.Where("city = ? ", o.LocationSpec.City)
346521
}
347522
if o.LocationSpec.SubZoneIsEmpty() {
523+
if len(o.SpecialSubZoneIds) > 0 {
524+
db.Where("sub_zone_id in (?)", o.SpecialSubZoneIds)
525+
}
348526
return
349527
}
350528
if o.LocationSpec.IncludeOrExclude {
351-
db.Where("sub_zone_id in ?", o.LocationSpec.SubZoneIds)
529+
db.Where("sub_zone_id in (?)", o.LocationSpec.SubZoneIds)
352530
} else {
353-
db.Where("sub_zone_id not in ?", o.LocationSpec.SubZoneIds)
531+
db.Where("sub_zone_id not in (?)", o.LocationSpec.SubZoneIds)
354532
}
355533
}
356534

dbm-services/common/db-resource/internal/svr/apply/apply_base.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,24 @@ type ActionInfo struct {
7171

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

82+
// GetAllAffinitys 获取这批请求的所有亲和性的参数
83+
func (param RequestInputParam) GetAllAffinitys() (affinitys []string) {
84+
for _, d := range param.Details {
85+
if !lo.Contains(affinitys, d.Affinity) {
86+
affinitys = append(affinitys, d.Affinity)
87+
}
88+
}
89+
return affinitys
90+
}
91+
8192
// BuildMessage build apply message
8293
func (param RequestInputParam) BuildMessage() (msg string) {
8394
var count int

0 commit comments

Comments
 (0)