diff --git a/pkg/cloudprovider/resources.go b/pkg/cloudprovider/resources.go index 299807ad3c..df0dc4bbca 100644 --- a/pkg/cloudprovider/resources.go +++ b/pkg/cloudprovider/resources.go @@ -218,6 +218,7 @@ type ICloudVM interface { GetMachine() string GetInstanceType() string + GetSecurityGroupIds() []string AssignSecurityGroup(secgroupId string) error SetSecurityGroups(secgroupIds []string) error diff --git a/pkg/compute/models/cloudsync.go b/pkg/compute/models/cloudsync.go index 1f21b419a9..18e418622d 100644 --- a/pkg/compute/models/cloudsync.go +++ b/pkg/compute/models/cloudsync.go @@ -176,9 +176,8 @@ func syncVpcSecGroup(ctx context.Context, userCred mcclient.TokenCredential, syn return } - _, _, result := SecurityGroupManager.SyncSecgroups(ctx, userCred, secgroups, localVpc, provider.ProjectId) - - syncResults.Add(SecurityGroupManager, result) + localSecgroups, removeSecgroups, result := SecurityGroupCacheManager.SyncSecurityGroupCaches(ctx, userCred, provider, secgroups, localVpc) + syncResults.Add(SecurityGroupCacheManager, result) msg := result.Result() notes := fmt.Sprintf("SyncSecurityGroup for VPC %s result: %s", localVpc.Name, msg) @@ -186,7 +185,33 @@ func syncVpcSecGroup(ctx context.Context, userCred mcclient.TokenCredential, syn if result.IsError() { return } + for i := 0; i < len(localSecgroups); i++ { + func() { + lockman.LockObject(ctx, &localSecgroups[i]) + defer lockman.ReleaseObject(ctx, &localSecgroups[i]) + syncSecurityGroupRules(ctx, userCred, syncResults, &localSecgroups[i], removeSecgroups[i]) + }() + } +} + +func syncSecurityGroupRules(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localSecgroup *SSecurityGroup, remoteSecgroup cloudprovider.ICloudSecurityGroup) { + rules, err := remoteSecgroup.GetRules() + if err != nil { + msg := fmt.Sprintf("Get SecurityGroup Rules for secgroup %s failed %s", localSecgroup.Name, err) + log.Errorf(msg) + return + } + + //可以同步规则的安全组都是本地刚新建的,所以安全组规则只需要添加就可以了 + result := SecurityGroupRuleManager.SyncRules(ctx, userCred, localSecgroup, rules) + syncResults.Add(SecurityGroupRuleManager, result) + msg := result.Result() + notes := fmt.Sprintf("SyncSecurityGroupRule for Secgroup %s result: %s", localSecgroup.Name, msg) + log.Infof(notes) + if result.IsError() { + return + } } func syncVpcRouteTables(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localVpc *SVpc, remoteVpc cloudprovider.ICloudVpc, syncRange *SSyncRange) { @@ -458,6 +483,7 @@ func syncHostVMs(ctx context.Context, userCred mcclient.TokenCredential, syncRes syncVMNics(ctx, userCred, provider, localHost, &localVMs[i], remoteVMs[i]) syncVMDisks(ctx, userCred, provider, driver, localHost, &localVMs[i], remoteVMs[i], syncRange) syncVMEip(ctx, userCred, provider, &localVMs[i], remoteVMs[i]) + syncVMSecgroups(ctx, userCred, provider, &localVMs[i], remoteVMs[i]) }() } @@ -515,6 +541,17 @@ func syncVMEip(ctx context.Context, userCred mcclient.TokenCredential, provider db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, userCred) } +func syncVMSecgroups(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, localVM *SGuest, remoteVM cloudprovider.ICloudVM) { + secgroupIds := remoteVM.GetSecurityGroupIds() + result := localVM.SyncVMSecgroups(ctx, userCred, provider, secgroupIds) + msg := result.Result() + log.Infof("SyncVMSecgroups for VM %s result: %s", localVM.Name, msg) + if result.IsError() { + return + } + db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, userCred) +} + func syncZoneSkusFromCloud(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localZone *SZone, remoteRegion cloudprovider.ICloudRegion, remoteZone cloudprovider.ICloudZone) { skus, err := remoteRegion.GetSkus(remoteZone.GetId()) if err != nil { diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index 35ac4c84e2..6dd1e11b7a 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -1852,7 +1852,6 @@ func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.Token self.HostId = host.Id } - metaData := extVM.GetMetadata() instanceType := extVM.GetInstanceType() if len(instanceType) > 0 { @@ -1879,26 +1878,6 @@ func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.Token self.ExpiredAt = extVM.GetExpiredAt() } - if metaData != nil && metaData.Contains("secgroupIds") { - secgroupIds := []string{} - if err := metaData.Unmarshal(&secgroupIds, "secgroupIds"); err == nil { - for _, secgroupId := range secgroupIds { - secgrp, err := SecurityGroupManager.FetchByExternalId(secgroupId) - if err != nil { - log.Errorf("Failed find secgroup %s for guest %s error: %v", secgroupId, self.Name, err) - continue - } - secgroup := secgrp.(*SSecurityGroup) - if len(self.SecgrpId) == 0 { - self.SecgrpId = secgroup.Id - } else { - if _, err := GuestsecgroupManager.newGuestSecgroup(ctx, userCred, self, secgroup); err != nil { - log.Errorf("failed to bind secgroup %s for guest %s error: %v", secgroup.Name, self.Name, err) - } - } - } - } - } return nil }) if err != nil { @@ -1947,7 +1926,6 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient. guest.HostId = host.Id - metaData := extVM.GetMetadata() instanceType := extVM.GetInstanceType() /*zoneExtId, err := metaData.GetString("zone_ext_id") @@ -1977,38 +1955,12 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient. guest.VmemSize = extVM.GetVmemSizeMB() } - extraSecgroups := []*SSecurityGroup{} - if metaData != nil && metaData.Contains("secgroupIds") { - secgroupIds := []string{} - if err := metaData.Unmarshal(&secgroupIds, "secgroupIds"); err == nil { - for _, secgroupId := range secgroupIds { - secgrp, err := SecurityGroupManager.FetchByExternalId(secgroupId) - if err != nil { - log.Errorf("Failed find secgroup %s for guest %s error: %v", secgroupId, guest.Name, err) - continue - } - secgroup := secgrp.(*SSecurityGroup) - if len(guest.SecgrpId) == 0 { - guest.SecgrpId = secgroup.Id - } else { - extraSecgroups = append(extraSecgroups, secgroup) - } - } - } - } - err := manager.TableSpec().Insert(&guest) if err != nil { log.Errorf("Insert fail %s", err) return nil, err } - for _, secgroup := range extraSecgroups { - if _, err := GuestsecgroupManager.newGuestSecgroup(ctx, userCred, &guest, secgroup); err != nil { - log.Errorf("failed to bind secgroup %s for guest %s error: %v", secgroup.Name, guest.Name, err) - } - } - db.OpsLog.LogEvent(&guest, db.ACT_CREATE, guest.GetShortDesc(ctx), userCred) SyncCloudProject(userCred, &guest, projectId, extVM, host.ManagerId) @@ -3782,6 +3734,76 @@ func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCreden return result } +func (self *SGuest) getSecgroupExternalIds(provider *SCloudprovider) []string { + secgroups := self.GetSecgroups() + secgroupids := []string{} + for i := 0; i < len(secgroups); i++ { + secgroupids = append(secgroupids, secgroups[i].Id) + } + q := SecurityGroupCacheManager.Query().Equals("manager_id", provider.Id) + q = q.Filter(sqlchemy.In(q.Field("secgroup_id"), secgroupids)) + secgroupcaches := []SSecurityGroupCache{} + if err := db.FetchModelObjects(SecurityGroupCacheManager, q, &secgroupcaches); err != nil { + log.Errorf("failed to fetch secgroupcaches for provider %s error: %v", provider.Name, err) + return nil + } + externalIds := []string{} + for i := 0; i < len(secgroupcaches); i++ { + externalIds = append(externalIds, secgroupcaches[i].ExternalId) + } + return externalIds +} + +func (self *SGuest) getSecgroupByCache(provider *SCloudprovider, externalId string) (*SSecurityGroup, error) { + q := SecurityGroupCacheManager.Query().Equals("manager_id", provider.Id).Equals("external_id", externalId) + cache := SSecurityGroupCache{} + cache.SetModelManager(SecurityGroupCacheManager) + count := q.Count() + if count == 0 { + return nil, fmt.Errorf("failed find secgroup cache from provider %s externalId %s", provider.Name, externalId) + } + if count > 1 { + return nil, fmt.Errorf("dumplicate secgroup cache for provider %s externalId %s", provider.Name, externalId) + } + if err := q.First(&cache); err != nil { + return nil, err + } + return cache.GetSecgroup() +} + +func (self *SGuest) SyncVMSecgroups(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, secgroupIds []string) compare.SyncResult { + syncResult := compare.SyncResult{} + + secgroupExternalIds := self.getSecgroupExternalIds(provider) + + for _, secgroupId := range secgroupIds { + if !utils.IsInStringArray(secgroupId, secgroupExternalIds) { + secgroup, err := self.getSecgroupByCache(provider, secgroupId) + if err != nil { + syncResult.AddError(err) + continue + } + if len(self.SecgrpId) == 0 { + _, err := db.Update(self, func() error { + self.SecgrpId = secgroup.Id + return nil + }) + if err != nil { + log.Errorf("update guest secgroup error: %v", err) + syncResult.AddError(err) + } + } else { + if _, err := GuestsecgroupManager.newGuestSecgroup(ctx, userCred, self, secgroup); err != nil { + log.Errorf("failed to bind secgroup %s for guest %s error: %v", secgroup.Name, self.Name, err) + syncResult.AddError(err) + } + } + syncResult.Add() + } + } + return syncResult +} + func (self *SGuest) GetIVM() (cloudprovider.ICloudVM, error) { if len(self.ExternalId) == 0 { msg := fmt.Sprintf("GetIVM: not managed by a provider") diff --git a/pkg/compute/models/secgroupcache.go b/pkg/compute/models/secgroupcache.go index 48585960f5..f278060faa 100644 --- a/pkg/compute/models/secgroupcache.go +++ b/pkg/compute/models/secgroupcache.go @@ -7,6 +7,7 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/pkg/util/compare" "yunion.io/x/pkg/util/stringutils" "yunion.io/x/sqlchemy" @@ -129,23 +130,6 @@ func (manager *SSecurityGroupCacheManager) GetSecgroupCache(ctx context.Context, return &secgroupCache } -func (manager *SSecurityGroupCacheManager) CheckExist(ctx context.Context, userCred mcclient.TokenCredential, externalId, vpcId, regionId string, providerId string) (*SSecurityGroup, bool) { - secgroupCaches := []SSecurityGroupCache{} - query := manager.Query() - cond := sqlchemy.AND(sqlchemy.Equals(query.Field("external_id"), externalId), sqlchemy.Equals(query.Field("vpc_id"), vpcId), sqlchemy.Equals(query.Field("cloudregion_id"), regionId), sqlchemy.Equals(query.Field("manager_id"), providerId)) - query = query.Filter(cond) - - if err := query.All(&secgroupCaches); err != nil { - return nil, false - } - for _, secgroupCache := range secgroupCaches { - if secgroup, err := SecurityGroupManager.FetchById(secgroupCache.SecgroupId); err == nil { - return secgroup.(*SSecurityGroup), true - } - } - return nil, false -} - func (manager *SSecurityGroupCacheManager) Register(ctx context.Context, userCred mcclient.TokenCredential, secgroupId, vpcId, regionId string, providerId string) *SSecurityGroupCache { lockman.LockClass(ctx, manager, userCred.GetProjectId()) defer lockman.ReleaseClass(ctx, manager, userCred.GetProjectId()) @@ -169,6 +153,73 @@ func (manager *SSecurityGroupCacheManager) Register(ctx context.Context, userCre return secgroupCache } +func (manager *SSecurityGroupCacheManager) getSecgroupcachesByProvider(provider *SCloudprovider) ([]SSecurityGroupCache, error) { + q := manager.Query().Equals("manager_id", provider.Id) + caches := []SSecurityGroupCache{} + if err := db.FetchModelObjects(manager, q, &caches); err != nil { + return nil, err + } + return caches, nil +} + +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 model.(*SSecurityGroup), nil +} + +func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, secgroups []cloudprovider.ICloudSecurityGroup, vpc *SVpc) ([]SSecurityGroup, []cloudprovider.ICloudSecurityGroup, compare.SyncResult) { + lockman.LockClass(ctx, manager, manager.GetOwnerId(userCred)) + defer lockman.ReleaseClass(ctx, manager, manager.GetOwnerId(userCred)) + + localSecgroups := []SSecurityGroup{} + remoteSecgroups := []cloudprovider.ICloudSecurityGroup{} + syncResult := compare.SyncResult{} + + dbSecgroupcaches, err := manager.getSecgroupcachesByProvider(provider) + if err != nil { + syncResult.Error(err) + return nil, nil, syncResult + } + + removed := []SSecurityGroupCache{} + commondb := []SSecurityGroupCache{} + commonext := []cloudprovider.ICloudSecurityGroup{} + added := []cloudprovider.ICloudSecurityGroup{} + + if err := compare.CompareSets(dbSecgroupcaches, secgroups, &removed, &commondb, &commonext, &added); err != nil { + syncResult.Error(err) + return nil, nil, syncResult + } + + //removed暂时删不了, 因为不能确定是哪个vpc底下的,有可能误删 + + //相同的不能同步, 原因: 多个平台的安全组可能共用一个本地安全组,下面仅仅是新加的安全组 + for i := 0; i < len(added); i++ { + secgroup, err := SecurityGroupManager.newFromCloudSecgroup(ctx, userCred, provider, added[i]) + if err != nil { + syncResult.AddError(err) + continue + } + cache := manager.Register(ctx, userCred, secgroup.Id, added[i].GetVpcId(), vpc.CloudregionId, provider.Id) + if cache == nil { + syncResult.AddError(fmt.Errorf("failed to registor secgroup cache for secgroup %s(%s) provider: %s", secgroup.Name, secgroup.Name, provider.Name)) + continue + } + if err := cache.SetExternalId(userCred, added[i].GetGlobalId()); err != nil { + syncResult.AddError(err) + continue + } + //每次同步完成出现新的安全组,同步规则时仅仅是添加 + localSecgroups = append(localSecgroups, *secgroup) + remoteSecgroups = append(remoteSecgroups, added[i]) + syncResult.Add() + } + return localSecgroups, remoteSecgroups, syncResult +} + func (self *SSecurityGroupCache) SetExternalId(userCred mcclient.TokenCredential, externalId string) error { diff, err := db.Update(self, func() error { self.ExternalId = externalId @@ -180,3 +231,7 @@ func (self *SSecurityGroupCache) SetExternalId(userCred mcclient.TokenCredential db.OpsLog.LogEvent(self, db.ACT_UPDATE, diff, userCred) return nil } + +func (self SSecurityGroupCache) GetExternalId() string { + return self.ExternalId +} diff --git a/pkg/compute/models/secgrouprules.go b/pkg/compute/models/secgrouprules.go index 975afdc5a8..ce11fc9fe7 100644 --- a/pkg/compute/models/secgrouprules.go +++ b/pkg/compute/models/secgrouprules.go @@ -3,7 +3,6 @@ package models import ( "context" "fmt" - "sort" "strconv" "strings" @@ -333,66 +332,17 @@ func (manager *SSecurityGroupRuleManager) getRulesBySecurityGroup(secgroup *SSec return rules, nil } -func (manager *SSecurityGroupRuleManager) SyncRules(ctx context.Context, userCred mcclient.TokenCredential, secgroup *SSecurityGroup, rules []secrules.SecurityRule) ([]SSecurityGroupRule, []SSecurityGroupRule, compare.SyncResult) { +func (manager *SSecurityGroupRuleManager) SyncRules(ctx context.Context, userCred mcclient.TokenCredential, secgroup *SSecurityGroup, rules []secrules.SecurityRule) compare.SyncResult { syncResult := compare.SyncResult{} - - if dbRules, err := manager.getRulesBySecurityGroup(secgroup); err != nil { - return nil, nil, syncResult - } else { - - sort.Sort(SecurityGroupRuleSet(dbRules)) - sort.Sort(secrules.SecurityRuleSet(rules)) - - i, j := 0, 0 - for i < len(rules) || j < len(dbRules) { - if i < len(rules) && j < len(dbRules) { - dbStr := dbRules[j].String() - ruleStr := rules[i].String() - cmp := strings.Compare(dbStr, ruleStr) - if cmp == 0 { - if dbRules[j].Description != rules[i].Description { - if _, err := db.Update(&dbRules[j], func() error { - dbRules[j].Description = rules[i].Description - return nil - }); err != nil { - log.Errorf("Update SecurityGroupRule failed: %v", err) - } - } - i += 1 - j += 1 - } else if cmp > 0 { - if err := dbRules[j].Delete(ctx, userCred); err != nil { - syncResult.AddError(err) - } else { - syncResult.Delete() - } - j += 1 - } else { - if _, err := manager.newFromCloudSecurityGroup(rules[i], secgroup); err != nil { - syncResult.AddError(err) - } else { - syncResult.Add() - } - i += 1 - } - } else if i >= len(rules) { - if err := dbRules[j].Delete(ctx, userCred); err != nil { - syncResult.AddError(err) - } else { - syncResult.Delete() - } - j += 1 - } else if j >= len(dbRules) { - if _, err := manager.newFromCloudSecurityGroup(rules[i], secgroup); err != nil { - syncResult.AddError(err) - } else { - syncResult.Add() - } - i += 1 - } + for i := 0; i < len(rules); i++ { + _, err := manager.newFromCloudSecurityGroup(rules[i], secgroup) + if err != nil { + syncResult.AddError(err) + continue } + syncResult.Add() } - return nil, nil, syncResult + return syncResult } func (manager *SSecurityGroupRuleManager) newFromCloudSecurityGroup(rule secrules.SecurityRule, secgroup *SSecurityGroup) (*SSecurityGroupRule, error) { diff --git a/pkg/compute/models/secgroups.go b/pkg/compute/models/secgroups.go index 6fce2bb90b..637c2e8172 100644 --- a/pkg/compute/models/secgroups.go +++ b/pkg/compute/models/secgroups.go @@ -8,7 +8,6 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" - "yunion.io/x/pkg/util/compare" "yunion.io/x/pkg/util/regutils" "yunion.io/x/pkg/util/secrules" "yunion.io/x/pkg/utils" @@ -263,119 +262,23 @@ func (manager *SSecurityGroupManager) getSecurityGroups() ([]SSecurityGroup, err } } -func (self *SSecurityGroup) SyncWithCloudSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, extSec cloudprovider.ICloudSecurityGroup, vpc *SVpc, projectId string) error { - if _, err := db.UpdateWithLock(ctx, self, func() error { - extSec.Refresh() - self.Name = extSec.GetName() - self.Description = extSec.GetDescription() - - return nil - }); err != nil { - log.Errorf("syncWithCloudSecurityGroup error %s", err) - return err - } - - SyncCloudProject(userCred, self, projectId, extSec, vpc.ManagerId) - - if secgroupcache := SecurityGroupCacheManager.Register(context.Background(), userCred, self.Id, extSec.GetVpcId(), vpc.CloudregionId, vpc.ManagerId); secgroupcache != nil { - if err := secgroupcache.SetExternalId(userCred, self.ExternalId); err != nil { - log.Errorf("set secgroupcache %s externalId error: %v", secgroupcache.Id, err) - } - } - - return nil -} - -func (manager *SSecurityGroupManager) newFromCloudVpc(ctx context.Context, userCred mcclient.TokenCredential, extSec cloudprovider.ICloudSecurityGroup, vpc *SVpc, projectId string) (*SSecurityGroup, bool, error) { - if secgroup, exist := SecurityGroupCacheManager.CheckExist(context.Background(), userCred, extSec.GetGlobalId(), extSec.GetVpcId(), vpc.CloudregionId, vpc.ManagerId); exist { - if secgroup.GetGuestsCount() == 0 { - return secgroup, true, nil - } - //避免重复同步 - return secgroup, false, nil - } - - secgroup := SSecurityGroup{} - secgroup.SetModelManager(manager) - secgroup.Name = extSec.GetName() - secgroup.ExternalId = extSec.GetGlobalId() - secgroup.Description = extSec.GetDescription() - - if err := manager.TableSpec().Insert(&secgroup); err != nil { - return nil, true, err - } - - db.OpsLog.LogEvent(&secgroup, db.ACT_CREATE, secgroup.GetShortDesc(ctx), userCred) - - SyncCloudProject(userCred, &secgroup, projectId, extSec, vpc.ManagerId) - - if secgroupcache := SecurityGroupCacheManager.Register(context.Background(), userCred, secgroup.Id, extSec.GetVpcId(), vpc.CloudregionId, vpc.ManagerId); secgroupcache != nil { - if err := secgroupcache.SetExternalId(userCred, secgroup.ExternalId); err != nil { - log.Errorf("set secgroupcache %s externalId error: %v", secgroupcache.Id, err) - } - } - - return &secgroup, true, nil -} - -func (manager *SSecurityGroupManager) SyncSecgroups(ctx context.Context, userCred mcclient.TokenCredential, secgroups []cloudprovider.ICloudSecurityGroup, vpc *SVpc, projectId string) ([]SSecurityGroup, []cloudprovider.ICloudSecurityGroup, compare.SyncResult) { +func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*SSecurityGroup, error) { lockman.LockClass(ctx, manager, manager.GetOwnerId(userCred)) defer lockman.ReleaseClass(ctx, manager, manager.GetOwnerId(userCred)) - localSecgroups := make([]SSecurityGroup, 0) - remoteSecgroups := make([]cloudprovider.ICloudSecurityGroup, 0) - syncResult := compare.SyncResult{} + secgroup := SSecurityGroup{} + secgroup.SetModelManager(manager) + secgroup.Name = db.GenerateName(manager, "", extSec.GetName()) + secgroup.Description = extSec.GetDescription() - dbSecgroups, err := manager.getSecurityGroups() - if err != nil { - syncResult.Error(err) - return nil, nil, syncResult - } - removed := make([]SSecurityGroup, 0) - commondb := make([]SSecurityGroup, 0) - commonext := make([]cloudprovider.ICloudSecurityGroup, 0) - added := make([]cloudprovider.ICloudSecurityGroup, 0) - - if err := compare.CompareSets(dbSecgroups, secgroups, &removed, &commondb, &commonext, &added); err != nil { - syncResult.Error(err) - return nil, nil, syncResult + if err := manager.TableSpec().Insert(&secgroup); err != nil { + return nil, err } - for i := 0; i < len(commondb); i += 1 { - rules, err := commonext[i].GetRules() - if err != nil { - syncResult.Error(err) - continue - } - if err := commondb[i].SyncWithCloudSecurityGroup(ctx, userCred, commonext[i], vpc, projectId); err != nil { - syncResult.UpdateError(err) - continue - } - localSecgroups = append(localSecgroups, commondb[i]) - remoteSecgroups = append(remoteSecgroups, commonext[i]) - SecurityGroupRuleManager.SyncRules(ctx, userCred, &commondb[i], rules) - syncResult.Update() - } + db.OpsLog.LogEvent(&secgroup, db.ACT_CREATE, secgroup.GetShortDesc(ctx), userCred) + SyncCloudProject(userCred, &secgroup, provider.ProjectId, extSec, provider.Id) - for i := 0; i < len(added); i += 1 { - rules, err := added[i].GetRules() - if err != nil { - syncResult.AddError(err) - continue - } - new, ruleSync, err := manager.newFromCloudVpc(ctx, userCred, added[i], vpc, projectId) - if err != nil { - syncResult.AddError(err) - continue - } - localSecgroups = append(localSecgroups, *new) - remoteSecgroups = append(remoteSecgroups, added[i]) - syncResult.Add() - if ruleSync { - SecurityGroupRuleManager.SyncRules(ctx, userCred, new, rules) - } - } - return localSecgroups, remoteSecgroups, syncResult + return &secgroup, nil } func (manager *SSecurityGroupManager) DelaySync(ctx context.Context, userCred mcclient.TokenCredential, idStr string) { diff --git a/pkg/util/aliyun/instance.go b/pkg/util/aliyun/instance.go index 51789a2ab2..1b1714c4ac 100644 --- a/pkg/util/aliyun/instance.go +++ b/pkg/util/aliyun/instance.go @@ -204,6 +204,10 @@ func (self *SRegion) fetchTags(resourceType string, resourceId string) (*jsonuti return tags, nil } +func (self *SInstance) GetSecurityGroupIds() []string { + return self.SecurityGroupIds.SecurityGroupId +} + func (self *SInstance) GetMetadata() *jsonutils.JSONDict { data := jsonutils.NewDict() @@ -229,11 +233,6 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict { data.Update(meta) } } - secgroupIds := jsonutils.NewArray() - for _, secgroupId := range self.SecurityGroupIds.SecurityGroupId { - secgroupIds.Add(jsonutils.NewString(secgroupId)) - } - data.Add(secgroupIds, "secgroupIds") return data } diff --git a/pkg/util/aws/instance.go b/pkg/util/aws/instance.go index fb78c961e3..7796527e4f 100644 --- a/pkg/util/aws/instance.go +++ b/pkg/util/aws/instance.go @@ -152,6 +152,10 @@ func (self *SInstance) GetInstanceType() string { return self.InstanceType } +func (self *SInstance) GetSecurityGroupIds() []string { + return self.SecurityGroupIds.SecurityGroupId +} + func (self *SInstance) GetMetadata() *jsonutils.JSONDict { data := jsonutils.NewDict() // todo: add price_key here @@ -177,11 +181,6 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict { data.Update(meta) } } - secgroupIds := jsonutils.NewArray() - for _, secgroupId := range self.SecurityGroupIds.SecurityGroupId { - secgroupIds.Add(jsonutils.NewString(secgroupId)) - } - data.Add(secgroupIds, "secgroupIds") return data } diff --git a/pkg/util/azure/classic_instance.go b/pkg/util/azure/classic_instance.go index b0b4f8641e..ed6ed3ff8a 100644 --- a/pkg/util/azure/classic_instance.go +++ b/pkg/util/azure/classic_instance.go @@ -127,16 +127,19 @@ type SClassicInstance struct { Location string } +func (self *SClassicInstance) GetSecurityGroupIds() []string { + secgroupIds := []string{} + if self.Properties.NetworkProfile.NetworkSecurityGroup != nil { + secgroupIds = append(secgroupIds, self.Properties.NetworkProfile.NetworkSecurityGroup.ID) + } + return secgroupIds +} + func (self *SClassicInstance) GetMetadata() *jsonutils.JSONDict { data := jsonutils.NewDict() priceKey := fmt.Sprintf("%s::%s", self.Properties.HardwareProfile.Size, self.host.zone.region.Name) data.Add(jsonutils.NewString(priceKey), "price_key") data.Add(jsonutils.NewString(self.host.zone.GetGlobalId()), "zone_ext_id") - secgroupIds := jsonutils.NewArray() - if self.Properties.NetworkProfile.NetworkSecurityGroup != nil { - secgroupIds.Add(jsonutils.NewString(self.Properties.NetworkProfile.NetworkSecurityGroup.ID)) - } - data.Add(secgroupIds, "secgroupIds") return data } diff --git a/pkg/util/azure/instance.go b/pkg/util/azure/instance.go index c5f1055d3e..14b3e2c041 100644 --- a/pkg/util/azure/instance.go +++ b/pkg/util/azure/instance.go @@ -193,6 +193,20 @@ func (self *SRegion) doDeleteVM(instanceId string) error { return self.client.Delete(instanceId) } +func (self *SInstance) GetSecurityGroupIds() []string { + secgroupIds := []string{} + if nics, err := self.getNics(); err == nil { + for _, nic := range nics { + if nic.Properties.NetworkSecurityGroup != nil { + if len(nic.Properties.NetworkSecurityGroup.ID) > 0 { + secgroupIds = append(secgroupIds, strings.ToLower(nic.Properties.NetworkSecurityGroup.ID)) + } + } + } + } + return secgroupIds +} + func (self *SInstance) GetMetadata() *jsonutils.JSONDict { data := jsonutils.NewDict() tags := jsonutils.NewDict() @@ -213,18 +227,6 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict { data.Add(jsonutils.NewString(self.host.zone.GetGlobalId()), "zone_ext_id") priceKey := fmt.Sprintf("%s::%s", self.Properties.HardwareProfile.VMSize, self.host.zone.region.Name) data.Add(jsonutils.NewString(priceKey), "price_key") - secgroupIds := jsonutils.NewArray() - if nics, err := self.getNics(); err == nil { - for _, nic := range nics { - if nic.Properties.NetworkSecurityGroup != nil { - if len(nic.Properties.NetworkSecurityGroup.ID) > 0 { - secgroupIds.Add(jsonutils.NewString(nic.Properties.NetworkSecurityGroup.ID)) - break - } - } - } - } - data.Add(secgroupIds, "secgroupIds") return data } diff --git a/pkg/util/esxi/virtualmachine.go b/pkg/util/esxi/virtualmachine.go index 520a678401..f8737349b4 100644 --- a/pkg/util/esxi/virtualmachine.go +++ b/pkg/util/esxi/virtualmachine.go @@ -42,6 +42,10 @@ func NewVirtualMachine(manager *SESXiClient, vm *mo.VirtualMachine, dc *SDatacen return svm } +func (self *SVirtualMachine) GetSecurityGroupIds() []string { + return []string{} +} + func (self *SVirtualMachine) GetMetadata() *jsonutils.JSONDict { return nil } diff --git a/pkg/util/huawei/instance.go b/pkg/util/huawei/instance.go index a40f0d09f3..49251870b1 100644 --- a/pkg/util/huawei/instance.go +++ b/pkg/util/huawei/instance.go @@ -222,6 +222,11 @@ func (self *SInstance) GetInstanceType() string { return self.Flavor.ID } +func (self *SInstance) GetSecurityGroupIds() []string { + secgroupIds, _ := self.host.zone.region.GetInstanceSecrityGroupIds(self.GetId()) + return secgroupIds +} + func (self *SInstance) GetMetadata() *jsonutils.JSONDict { data := jsonutils.NewDict() // cn-north-1::et2.2xlarge.16::win @@ -239,17 +244,6 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict { data.Update(meta) } } - - _secIds, err := self.host.zone.region.GetInstanceSecrityGroupIds(self.GetId()) - if err != nil { - log.Errorf(err.Error()) - } else { - secgroupIds := jsonutils.NewArray() - for _, secId := range _secIds { - secgroupIds.Add(jsonutils.NewString(secId)) - } - data.Add(secgroupIds, "secgroupIds") - } return data } diff --git a/pkg/util/openstack/instance.go b/pkg/util/openstack/instance.go index 510870463c..aa32e45398 100644 --- a/pkg/util/openstack/instance.go +++ b/pkg/util/openstack/instance.go @@ -162,17 +162,19 @@ func (region *SRegion) GetInstance(instanceId string) (*SInstance, error) { return instance, resp.Unmarshal(instance, "server") } -func (instance *SInstance) GetMetadata() *jsonutils.JSONDict { - data := jsonutils.NewDict() - +func (instance *SInstance) GetSecurityGroupIds() []string { + secgroupIds := []string{} secgroups, err := instance.host.zone.region.GetSecurityGroupsByInstance(instance.ID) if err == nil { - secgroupIds := jsonutils.NewArray() for _, secgroup := range secgroups { - secgroupIds.Add(jsonutils.NewString(secgroup.ID)) + secgroupIds = append(secgroupIds, secgroup.ID) } - data.Add(secgroupIds, "secgroupIds") } + return secgroupIds +} + +func (instance *SInstance) GetMetadata() *jsonutils.JSONDict { + data := jsonutils.NewDict() instance.fetchFlavor() diff --git a/pkg/util/qcloud/instance.go b/pkg/util/qcloud/instance.go index 650cfdc648..5ed48cb9f0 100644 --- a/pkg/util/qcloud/instance.go +++ b/pkg/util/qcloud/instance.go @@ -138,6 +138,10 @@ func (self *SRegion) GetInstances(zoneId string, ids []string, offset int, limit return instances, int(total), nil } +func (self *SInstance) GetSecurityGroupIds() []string { + return self.SecurityGroupIds +} + func (self *SInstance) GetMetadata() *jsonutils.JSONDict { data := jsonutils.NewDict() if self.image == nil { @@ -155,11 +159,6 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict { data.Add(jsonutils.NewString(priceKey), "price_key") data.Add(jsonutils.NewString(self.host.zone.GetGlobalId()), "zone_ext_id") - secgroupIds := jsonutils.NewArray() - for _, secgroupId := range self.SecurityGroupIds { - secgroupIds.Add(jsonutils.NewString(secgroupId)) - } - data.Add(secgroupIds, "secgroupIds") return data }