Merge pull request #9690 from ioito/hotfix/qx-secgroup-optimized

fix(region): optimized secgroup rule sync
This commit is contained in:
Zexi Li
2021-01-12 21:37:56 +08:00
committed by GitHub
6 changed files with 167 additions and 74 deletions
+3 -2
View File
@@ -15,8 +15,9 @@
package compute
const (
SECGROUP_STATUS_READY = "ready"
SECGROUP_STATUS_DELETING = "deleting"
SECGROUP_STATUS_READY = "ready"
SECGROUP_STATUS_DELETING = "deleting" // 删除中
SECGROUP_STATUS_SYNC_RULES = "sync_rules" // 同步规则中
SECGROUP_DEFAULT_ID = "default"
)
+8 -43
View File
@@ -32,7 +32,6 @@ import (
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/pkg/util/osprofile"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/pkg/util/timeutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
@@ -2317,20 +2316,9 @@ func (self *SGuest) GetSecgroups() ([]SSecurityGroup, error) {
return secgroups, nil
}
func (self *SGuest) getSecgroup() *SSecurityGroup {
return SecurityGroupManager.FetchSecgroupById(self.SecgrpId)
}
func (self *SGuest) getAdminSecgroup() *SSecurityGroup {
return SecurityGroupManager.FetchSecgroupById(self.AdminSecgrpId)
}
func (self *SGuest) GetSecgroupName() string {
secgrp := self.getSecgroup()
if secgrp != nil {
return secgrp.GetName()
}
return ""
secGrp, _ := SecurityGroupManager.FetchSecgroupById(self.AdminSecgrpId)
return secGrp
}
func (self *SGuest) getAdminSecgroupName() string {
@@ -2341,31 +2329,6 @@ func (self *SGuest) getAdminSecgroupName() string {
return ""
}
func (self *SGuest) GetSecRules() []secrules.SecurityRule {
return self.getSecRules()
}
func (self *SGuest) getSecRules() []secrules.SecurityRule {
if secgrp := self.getSecgroup(); secgrp != nil {
return secgrp.GetSecRules("")
}
if rule, err := secrules.ParseSecurityRule(options.Options.DefaultSecurityRules); err == nil {
return []secrules.SecurityRule{*rule}
} else {
log.Errorf("Default SecurityRules error: %v", err)
}
return []secrules.SecurityRule{}
}
func (self *SGuest) getSecurityRules() string {
secgrp := self.getSecgroup()
if secgrp != nil {
return secgrp.getSecurityRuleString("")
} else {
return options.Options.DefaultSecurityRules
}
}
//获取多个安全组规则,优先级降序排序
func (self *SGuest) getSecurityGroupsRules() string {
secgroups, _ := self.GetSecgroups()
@@ -4089,10 +4052,12 @@ func (self *SGuest) GetJsonDescAtHypervisor(ctx context.Context, host *SHost) *j
desc.Add(jsonutils.NewStringArray(netRoles), "network_roles")
}
secGrp := self.getSecgroup()
if secGrp != nil {
desc.Add(jsonutils.NewString(secGrp.Name), "secgroup")
}
/*
secGrp := self.getSecgroup()
if secGrp != nil {
desc.Add(jsonutils.NewString(secGrp.Name), "secgroup")
}
*/
secgroups, _ := self.getSecgroupJson()
if secgroups != nil {
+2 -1
View File
@@ -430,7 +430,8 @@ func (self *SInstanceSnapshot) ToInstanceCreateInput(
inputSecgs := make([]string, 0)
self.SecGroups.Unmarshal(&secGroups)
for i := 0; i < len(secGroups); i++ {
if secGrp := SecurityGroupManager.FetchSecgroupById(secGroups[i]); secGrp != nil {
_, err := SecurityGroupManager.FetchSecgroupById(secGroups[i])
if err == nil {
inputSecgs = append(inputSecgs, secGroups[i])
}
}
+38
View File
@@ -23,6 +23,7 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
@@ -630,3 +631,40 @@ func (self *SSecurityGroupCache) GetISecurityGroup() (cloudprovider.ICloudSecuri
}
return iRegion.GetISecurityGroupById(self.ExternalId)
}
func (self *SSecurityGroupCache) SyncRules() error {
region := self.GetRegion()
if region == nil {
return fmt.Errorf("failed to get region for secgroupcache %s(%s)", self.Name, self.Id)
}
iSecgroup, err := self.GetISecurityGroup()
if err != nil {
return errors.Wrapf(err, "GetISecurityGroup")
}
secgroup, err := self.GetSecgroup()
if err != nil {
return errors.Wrapf(err, "GetSecgroup")
}
rules, err := iSecgroup.GetRules()
if err != nil {
return errors.Wrapf(err, "iSecgroup.GetRules")
}
maxPriority := region.GetDriver().GetSecurityGroupRuleMaxPriority()
minPriority := region.GetDriver().GetSecurityGroupRuleMinPriority()
defaultInRule := region.GetDriver().GetDefaultSecurityGroupInRule()
defaultOutRule := region.GetDriver().GetDefaultSecurityGroupOutRule()
order := region.GetDriver().GetSecurityGroupRuleOrder()
onlyAllowRules := region.GetDriver().IsOnlySupportAllowRules()
localRules := secrules.SecurityRuleSet(secgroup.GetSecRules(""))
common, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(minPriority, maxPriority, order, localRules, rules, defaultInRule, defaultOutRule, onlyAllowRules, false)
if len(inAdds) == 0 && len(inDels) == 0 && len(outAdds) == 0 && len(outDels) == 0 {
return nil
}
return iSecgroup.SyncRules(common, inAdds, outAdds, inDels, outDels)
}
+52 -28
View File
@@ -291,6 +291,16 @@ func (self *SSecurityGroup) GetGuests() []SGuest {
return guests
}
func (self *SSecurityGroup) GetKvmGuests() ([]SGuest, error) {
guests := []SGuest{}
q := self.GetGuestsQuery().Equals("hypervisor", api.HYPERVISOR_KVM)
err := db.FetchModelObjects(GuestManager, q, &guests)
if err != nil {
return nil, errors.Wrapf(err, "db.FetchModelObjects")
}
return guests, nil
}
func (self *SSecurityGroup) GetSecgroupCacheQuery() *sqlchemy.SQuery {
return SecurityGroupCacheManager.Query().Equals("secgroup_id", self.Id)
}
@@ -529,14 +539,12 @@ func (self *SSecurityGroup) PostCreate(ctx context.Context, userCred mcclient.To
}
}
func (manager *SSecurityGroupManager) FetchSecgroupById(secId string) *SSecurityGroup {
if len(secId) > 0 {
secgrp, _ := manager.FetchById(secId)
if secgrp != nil {
return secgrp.(*SSecurityGroup)
}
func (manager *SSecurityGroupManager) FetchSecgroupById(secId string) (*SSecurityGroup, error) {
secgrp, err := manager.FetchById(secId)
if err != nil {
return nil, errors.Wrapf(err, "FetchById(%s)", secId)
}
return nil
return secgrp.(*SSecurityGroup), nil
}
func (self *SSecurityGroup) getSecurityRules(direction string) (rules []SSecurityGroupRule) {
@@ -1027,33 +1035,49 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
return &secgroup, nil
}
func (manager *SSecurityGroupManager) DelaySync(ctx context.Context, userCred mcclient.TokenCredential, idStr string) {
if secgrp := manager.FetchSecgroupById(idStr); secgrp == nil {
log.Errorf("DelaySync secgroup failed")
} else {
needSync := false
func (manager *SSecurityGroupManager) DelaySync(ctx context.Context, userCred mcclient.TokenCredential, idStr string) error {
secgrp, err := manager.FetchSecgroupById(idStr)
if err != nil {
return errors.Wrapf(err, "FetchSecgroupById(%s)", idStr)
}
needSync := false
func() {
lockman.LockObject(ctx, secgrp)
defer lockman.ReleaseObject(ctx, secgrp)
func() {
lockman.LockObject(ctx, secgrp)
defer lockman.ReleaseObject(ctx, secgrp)
if secgrp.IsDirty {
if _, err := db.Update(secgrp, func() error {
secgrp.IsDirty = false
return nil
}); err != nil {
log.Errorf("Update Security Group error: %s", err.Error())
}
needSync = true
if secgrp.IsDirty {
if _, err := db.Update(secgrp, func() error {
secgrp.IsDirty = false
return nil
}); err != nil {
log.Errorf("Update Security Group error: %s", err.Error())
}
}()
needSync = true
}
}()
if needSync {
for _, guest := range secgrp.GetGuests() {
guest.StartSyncTask(ctx, userCred, true, "")
}
if needSync {
guests, err := secgrp.GetKvmGuests()
if err != nil {
return errors.Wrapf(err, "GetKvmGuests")
}
for _, guest := range guests {
guest.StartSyncTask(ctx, userCred, true, "")
}
}
return secgrp.StartSecurityGroupSyncRulesTask(ctx, userCred, "")
}
func (self *SSecurityGroup) StartSecurityGroupSyncRulesTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
params := jsonutils.NewDict()
task, err := taskman.TaskManager.NewTask(ctx, "SecurityGroupSyncRulesTask", self, userCred, params, parentTaskId, "", nil)
if err != nil {
return errors.Wrapf(err, "NewTask")
}
self.SetStatus(userCred, api.SECGROUP_STATUS_SYNC_RULES, "")
task.ScheduleRun(nil)
return nil
}
func (self *SSecurityGroup) DoSync(ctx context.Context, userCred mcclient.TokenCredential) {
@@ -0,0 +1,64 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tasks
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/util/logclient"
)
type SecurityGroupSyncRulesTask struct {
taskman.STask
}
func init() {
taskman.RegisterTask(SecurityGroupSyncRulesTask{})
}
func (self *SecurityGroupSyncRulesTask) taskFailed(ctx context.Context, secgroup *models.SSecurityGroup, err error) {
secgroup.SetStatus(self.UserCred, api.SECGROUP_STATUS_READY, "")
logclient.AddActionLogWithContext(ctx, secgroup, logclient.ACT_SYNC_CONF, err, self.UserCred, false)
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
}
func (self *SecurityGroupSyncRulesTask) taskComplete(ctx context.Context, secgroup *models.SSecurityGroup) {
secgroup.SetStatus(self.UserCred, api.SECGROUP_STATUS_READY, "")
self.SetStageComplete(ctx, nil)
}
func (self *SecurityGroupSyncRulesTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
secgroup := obj.(*models.SSecurityGroup)
caches, err := secgroup.GetSecurityGroupCaches()
if err != nil {
self.taskFailed(ctx, secgroup, errors.Wrapf(err, "GetSecurityGroupCaches"))
return
}
for i := range caches {
err := caches[i].SyncRules()
if err != nil {
logclient.AddActionLogWithContext(ctx, secgroup, logclient.ACT_SYNC_CONF, errors.Wrapf(err, "SyncRules"), self.UserCred, false)
}
}
self.taskComplete(ctx, secgroup)
}