mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #13008 from ioito/hotfix/qx-secgroup-purge
fix(region): secgroup purge with cloudaccount deleted
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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, "")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user