Merge pull request #13008 from ioito/hotfix/qx-secgroup-purge

fix(region): secgroup purge with cloudaccount deleted
This commit is contained in:
Zexi Li
2021-12-28 10:55:33 +08:00
committed by GitHub
4 changed files with 97 additions and 18 deletions
+12
View File
@@ -321,3 +321,15 @@ type SecgroupJsonDesc struct {
Id string `json:"id"`
Name string `json:"name"`
}
type SSecurityGroupRef struct {
GuestCnt int `json:"guest_cnt"`
AdminGuestCnt int `json:"admin_guest_cnt"`
RdsCnt int `json:"rds_cnt"`
RedisCnt int `json:"redis_cnt"`
TotalCnt int `json:"total_cnt"`
}
func (self *SSecurityGroupRef) Sum() {
self.TotalCnt = self.GuestCnt + self.AdminGuestCnt + self.RdsCnt + self.RedisCnt
}
-7
View File
@@ -1804,13 +1804,6 @@ func (manager *SElasticcacheManager) purgeAll(ctx context.Context, userCred mccl
return nil
}
func (cache *SSecurityGroupCache) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, cache)
defer lockman.ReleaseObject(ctx, cache)
return cache.RealDelete(ctx, userCred)
}
func (manager *SSecurityGroupCacheManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
caches := []SSecurityGroupCache{}
err := fetchByManagerId(manager, providerId, &caches)
+21 -3
View File
@@ -46,7 +46,6 @@ type SSecurityGroupCacheManager struct {
SCloudregionResourceBaseManager
SVpcResourceBaseManager
SSecurityGroupResourceBaseManager
SGlobalVpcResourceBaseManager
}
type SSecurityGroupCache struct {
@@ -55,7 +54,6 @@ type SSecurityGroupCache struct {
SCloudregionResourceBase
SManagedResourceBase
SSecurityGroupResourceBase
SGlobalVpcResourceBase `width:"36" charset:"ascii" list:"user" json:"globalvpc_id"`
// 被其他安全组引用的次数
ReferenceCount int `nullable:"false" list:"user" json:"reference_count"`
@@ -361,7 +359,7 @@ func (manager *SSecurityGroupCacheManager) getSecgroupcachesByProvider(provider
func (self *SSecurityGroupCache) GetSecgroup() (*SSecurityGroup, error) {
model, err := SecurityGroupManager.FetchById(self.SecgroupId)
if err != nil {
return nil, fmt.Errorf("failed to fetch secgroup by %s", self.SecgroupId)
return nil, errors.Wrapf(err, "SecurityGroupManager.FetchById(%s)", self.SecgroupId)
}
return model.(*SSecurityGroup), nil
}
@@ -574,6 +572,26 @@ func (self *SSecurityGroupCache) RealDelete(ctx context.Context, userCred mcclie
return self.SStatusStandaloneResourceBase.Delete(ctx, userCred)
}
func (self *SSecurityGroupCache) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
if secgroup, _ := self.GetSecgroup(); secgroup != nil {
caches, err := secgroup.GetSecurityGroupCaches()
if err != nil {
return errors.Wrapf(err, "secgroup.GetSecurityGroupCaches")
}
if len(caches) == 1 {
err := secgroup.ValidateDeleteCondition(ctx, nil)
if err == nil {
secgroup.RealDelete(ctx, userCred)
}
}
}
return self.RealDelete(ctx, userCred)
}
func (self *SSecurityGroupCache) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
return self.StartSecurityGroupCacheDeleteTask(ctx, userCred, "")
}
+64 -8
View File
@@ -1189,7 +1189,7 @@ func (manager *SSecurityGroupManager) InitializeData() error {
log.Debugf("Init default secgroup")
secGrp := &SSecurityGroup{}
secGrp.SetModelManager(manager, secGrp)
secGrp.Id = "default"
secGrp.Id = api.SECGROUP_DEFAULT_ID
secGrp.Name = "Default"
secGrp.Status = api.SECGROUP_STATUS_READY
secGrp.ProjectId = auth.AdminCredential().GetProjectId()
@@ -1210,7 +1210,7 @@ func (manager *SSecurityGroupManager) InitializeData() error {
defRule.Priority = 1
defRule.CIDR = "0.0.0.0/0"
defRule.Action = string(secrules.SecurityRuleAllow)
defRule.SecgroupId = "default"
defRule.SecgroupId = api.SECGROUP_DEFAULT_ID
err = SecurityGroupRuleManager.TableSpec().Insert(context.TODO(), &defRule)
if err != nil {
return errors.Wrapf(err, "Insert default secgroup rule")
@@ -1260,17 +1260,73 @@ func (self *SSecurityGroup) GetSecurityGroupReferences() ([]SSecurityGroup, erro
return groups, nil
}
func (self *SSecurityGroup) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
cnt, err := self.GetGuestsCount()
func (sm *SSecurityGroupManager) query(manager db.IModelManager, field, label string, secIds []string) *sqlchemy.SSubQuery {
sq := manager.Query().SubQuery()
return sq.Query(
sq.Field(field),
sqlchemy.COUNT(label),
).In(field, secIds).GroupBy(sq.Field(field)).SubQuery()
}
type sSecuriyGroupCnts struct {
Id string
Guest1Cnt int
api.SSecurityGroupRef
}
func (sm *SSecurityGroupManager) TotalCnt(secIds []string) (map[string]api.SSecurityGroupRef, error) {
g1SQ := sm.query(GuestsecgroupManager, "secgroup_id", "guest1", secIds)
g2SQ := sm.query(GuestManager, "secgrp_id", "guest2", secIds)
g3SQ := sm.query(GuestManager, "admin_secgrp_id", "guest3", secIds)
rdsSQ := sm.query(DBInstanceSecgroupManager, "secgroup_id", "rds", secIds)
redisSQ := sm.query(ElasticcachesecgroupManager, "secgroup_id", "redis", secIds)
secs := sm.Query().SubQuery()
secQ := secs.Query(
sqlchemy.SUM("guest_cnt", g1SQ.Field("guest1")),
sqlchemy.SUM("guest1_cnt", g2SQ.Field("guest2")),
sqlchemy.SUM("admin_guest_cnt", g3SQ.Field("guest3")),
sqlchemy.SUM("rds_cnt", rdsSQ.Field("rds")),
sqlchemy.SUM("redis_cnt", redisSQ.Field("redis")),
)
secQ.AppendField(secQ.Field("id"))
secQ = secQ.LeftJoin(g1SQ, sqlchemy.Equals(secQ.Field("id"), g1SQ.Field("secgroup_id")))
secQ = secQ.LeftJoin(g2SQ, sqlchemy.Equals(secQ.Field("id"), g2SQ.Field("secgrp_id")))
secQ = secQ.LeftJoin(g3SQ, sqlchemy.Equals(secQ.Field("id"), g3SQ.Field("admin_secgrp_id")))
secQ = secQ.LeftJoin(rdsSQ, sqlchemy.Equals(secQ.Field("id"), rdsSQ.Field("secgroup_id")))
secQ = secQ.LeftJoin(redisSQ, sqlchemy.Equals(secQ.Field("id"), redisSQ.Field("secgroup_id")))
secQ = secQ.Filter(sqlchemy.In(secQ.Field("id"), secIds)).GroupBy(secQ.Field("id"))
cnts := []sSecuriyGroupCnts{}
err := secQ.All(&cnts)
if err != nil {
return httperrors.NewInternalServerError("GetGuestsCount fail %s", err)
return nil, errors.Wrapf(err, "secQ.All")
}
if cnt > 0 {
return httperrors.NewNotEmptyError("the security group is in use")
result := map[string]api.SSecurityGroupRef{}
for i := range cnts {
cnts[i].GuestCnt += cnts[i].Guest1Cnt
cnts[i].Sum()
result[cnts[i].Id] = cnts[i].SSecurityGroupRef
}
if self.Id == "default" {
return result, nil
}
func (self *SSecurityGroup) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
if self.Id == api.SECGROUP_DEFAULT_ID {
return httperrors.NewProtectedResourceError("not allow to delete default security group")
}
cnts, err := SecurityGroupManager.TotalCnt([]string{self.Id})
if err != nil {
return errors.Wrapf(err, "SecurityGroupManager.TotalCnt")
}
if cnt, ok := cnts[self.Id]; ok && cnt.TotalCnt > 0 {
return httperrors.NewNotEmptyError("the security group %s is in use cnt: %s", self.Id, jsonutils.Marshal(cnt).String())
}
references, err := self.GetSecurityGroupReferences()
if err != nil {
return httperrors.NewGeneralError(err)