fix: secgroup cache reference

This commit is contained in:
Qu Xuan
2021-04-02 16:20:31 +08:00
parent 45538dc807
commit 2d57443765
13 changed files with 274 additions and 48 deletions
+8 -40
View File
@@ -15,48 +15,16 @@
package compute
import (
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/cmd/climc/shell"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/options"
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
)
func init() {
type SecGroupCacheListOptions struct {
options.BaseListOptions
Secgroup string `help:"Secgroup ID or Name"`
}
R(&SecGroupCacheListOptions{}, "secgroup-cache-list", "List security group caches", func(s *mcclient.ClientSession, args *SecGroupCacheListOptions) error {
params, err := options.ListStructToParams(args)
if err != nil {
return err
}
result, err := modules.SecGroupCaches.List(s, params)
if err != nil {
return err
}
printList(result, modules.SecGroupCaches.GetColumns(s))
return nil
})
type SecGroupCacheIdOptions struct {
ID string `help:"ID or Name or secgroup cache"`
}
R(&SecGroupCacheIdOptions{}, "secgroup-cache-show", "Show security group cache", func(s *mcclient.ClientSession, args *SecGroupCacheIdOptions) error {
result, err := modules.SecGroupCaches.Get(s, args.ID, nil)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&SecGroupCacheIdOptions{}, "secgroup-cache-delete", "Delete security group cache", func(s *mcclient.ClientSession, args *SecGroupCacheIdOptions) error {
result, err := modules.SecGroupCaches.Delete(s, args.ID, nil)
if err != nil {
return err
}
printObject(result)
return nil
})
cmd := shell.NewResourceCmd(&modules.SecGroupCaches).WithKeyword("secgroup-cache")
cmd.List(&compute.SecGroupCacheListOptions{})
cmd.Show(&compute.SecGroupCacheIdOptions{})
cmd.Delete(&compute.SecGroupCacheIdOptions{})
cmd.Perform("syncstatus", &compute.SecGroupCacheIdOptions{})
cmd.Get("references", &compute.SecGroupCacheIdOptions{})
}
+1
View File
@@ -16,6 +16,7 @@ package compute
const (
SECGROUP_CACHE_STATUS_READY = "ready"
SECGROUP_CACHE_STATUS_UNKNOWN = "unknown"
SECGROUP_CACHE_STATUS_DELETING = "deleting"
SECGROUP_CACHE_STATUS_CACHING = "caching"
SECGROUP_CACHE_STATUS_DELETE_FAILED = "delete_failed"
+1
View File
@@ -415,6 +415,7 @@ type ICloudSecurityGroup interface {
GetVpcId() string
SyncRules(common, inAdds, outAdds, inDels, outDels []SecurityRule) error
GetReferences() ([]SecurityGroupReference, error)
Delete() error
}
+4
View File
@@ -26,6 +26,10 @@ import (
"yunion.io/x/pkg/utils"
)
type SecurityGroupReference struct {
Id string
}
type SecDriver interface {
GetDefaultSecurityGroupInRule() SecurityRule
GetDefaultSecurityGroupOutRule() SecurityRule
-5
View File
@@ -1693,11 +1693,6 @@ func (cache *SSecurityGroupCache) purge(ctx context.Context, userCred mcclient.T
lockman.LockObject(ctx, cache)
defer lockman.ReleaseObject(ctx, cache)
err := cache.ValidateDeleteCondition(ctx)
if err != nil {
return err
}
return cache.RealDelete(ctx, userCred)
}
+52 -1
View File
@@ -55,6 +55,9 @@ type SSecurityGroupCache struct {
SManagedResourceBase
SSecurityGroupResourceBase
// 被其他安全组引用的次数
ReferenceCount int `nullable:"false" list:"user" json:"reference_count"`
// 安全组Id
// SecgroupId string `width:"128" charset:"ascii" list:"user" create:"required"`
@@ -388,14 +391,26 @@ func (self *SSecurityGroupCache) GetSecgroup() (*SSecurityGroup, error) {
return model.(*SSecurityGroup), nil
}
func (self *SSecurityGroupCache) syncWithCloudSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudSecurityGroup) ([]SSecurityGroupRule, error) {
func (self *SSecurityGroupCache) SyncBaseInfo(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudSecurityGroup) error {
_, err := db.Update(self, func() error {
self.Status = api.SECGROUP_CACHE_STATUS_READY
self.Name = ext.GetName()
self.Description = ext.GetDescription()
self.ExternalProjectId = ext.GetProjectId()
references, err := ext.GetReferences()
if err == nil {
self.ReferenceCount = len(references)
}
return nil
})
if err != nil {
return errors.Wrapf(err, "db.Update")
}
return nil
}
func (self *SSecurityGroupCache) syncWithCloudSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudSecurityGroup) ([]SSecurityGroupRule, error) {
err := self.SyncBaseInfo(ctx, userCred, ext)
if err != nil {
return nil, errors.Wrapf(err, "db.Update")
}
@@ -519,6 +534,8 @@ func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.C
cache.Name = added[i].GetName()
cache.Description = added[i].GetDescription()
cache.ExternalId = added[i].GetGlobalId()
references, _ := added[i].GetReferences()
cache.ReferenceCount = len(references)
return nil
})
if err != nil {
@@ -543,6 +560,40 @@ func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.C
return localSecgroups, remoteSecgroups, syncResult
}
func (self *SSecurityGroupCache) AllowPerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsProjectAllowPerform(userCred, self, "syncstatus")
}
// 同步安全组缓存状态
func (self *SSecurityGroupCache) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.DiskSyncstatusInput) (jsonutils.JSONObject, error) {
return nil, self.StartSyncstatusTask(ctx, userCred, "")
}
func (self *SSecurityGroupCache) AllowGetDetailsReferences(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowGetSpec(userCred, self, "references")
}
// 获取引用信息
func (self *SSecurityGroupCache) GetDetailsReferences(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) ([]cloudprovider.SecurityGroupReference, error) {
iSecgroup, err := self.GetISecurityGroup()
if err != nil {
return nil, errors.Wrapf(err, "GetISecurityGroup")
}
return iSecgroup.GetReferences()
}
func (self *SSecurityGroupCache) StartSyncstatusTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
return StartResourceSyncStatusTask(ctx, userCred, self, "SecurityGroupCacheSyncstatusTask", "")
}
func (self *SSecurityGroupCache) ValidateDeleteCondition(ctx context.Context) error {
if self.ReferenceCount > 0 && self.Status == api.SECGROUP_CACHE_STATUS_READY {
return httperrors.NewNotEmptyError("security group has been reference in %d security group", self.ReferenceCount)
}
return self.SStatusStandaloneResourceBase.ValidateDeleteCondition(ctx)
}
func (self *SSecurityGroupCache) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
log.Infof("do nothing for delete secgroup cache")
return nil
@@ -0,0 +1,54 @@
// 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"
)
type SecurityGroupCacheSyncstatusTask struct {
taskman.STask
}
func init() {
taskman.RegisterTask(SecurityGroupCacheSyncstatusTask{})
}
func (self *SecurityGroupCacheSyncstatusTask) taskFailed(ctx context.Context, cache *models.SSecurityGroupCache, err error) {
cache.SetStatus(self.UserCred, api.SECGROUP_CACHE_STATUS_UNKNOWN, err.Error())
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
}
func (self *SecurityGroupCacheSyncstatusTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
cache := obj.(*models.SSecurityGroupCache)
iSecgroup, err := cache.GetISecurityGroup()
if err != nil {
self.taskFailed(ctx, cache, errors.Wrapf(err, "GetISecurityGroup"))
return
}
cache.SyncBaseInfo(ctx, self.GetUserCred(), iSecgroup)
self.SetStageComplete(ctx, nil)
}
@@ -0,0 +1,42 @@
// 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 compute
import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient/options"
)
type SecGroupCacheListOptions struct {
options.BaseListOptions
Secgroup string `help:"Secgroup ID or Name"`
}
func (opts *SecGroupCacheListOptions) Params() (jsonutils.JSONObject, error) {
return options.ListStructToParams(opts)
}
type SecGroupCacheIdOptions struct {
ID string `help:"ID or Name or secgroup cache"`
}
func (opts *SecGroupCacheIdOptions) GetId() string {
return opts.ID
}
func (opts *SecGroupCacheIdOptions) Params() (jsonutils.JSONObject, error) {
return nil, nil
}
+46
View File
@@ -150,6 +150,52 @@ func (self *SSecurityGroup) Refresh() error {
return jsonutils.Update(self, group)
}
func (self *SSecurityGroup) GetReferences() ([]cloudprovider.SecurityGroupReference, error) {
references, err := self.vpc.region.DescribeSecurityGroupReferences(self.SecurityGroupId)
if err != nil {
return nil, errors.Wrapf(err, "DescribeSecurityGroupReferences")
}
ret := []cloudprovider.SecurityGroupReference{}
for _, reference := range references {
if reference.SecurityGroupId == self.SecurityGroupId {
for _, sec := range reference.ReferencingSecurityGroups.ReferencingSecurityGroup {
ret = append(ret, cloudprovider.SecurityGroupReference{
Id: sec.SecurityGroupId,
})
}
}
}
return ret, nil
}
type ReferencingSecurityGroup struct {
AliUid string
SecurityGroupId string
}
type ReferencingSecurityGroups struct {
ReferencingSecurityGroup []ReferencingSecurityGroup
}
type SecurityGroupReferences struct {
SecurityGroupId string
ReferencingSecurityGroups ReferencingSecurityGroups
}
func (self *SRegion) DescribeSecurityGroupReferences(id string) ([]SecurityGroupReferences, error) {
params := map[string]string{
"RegionId": self.RegionId,
"SecurityGroupId.1": id,
}
resp, err := self.ecsRequest("DescribeSecurityGroupReferences", params)
if err != nil {
return nil, errors.Wrapf(err, "DescribeSecurityGroupReferences")
}
ret := []SecurityGroupReferences{}
err = resp.Unmarshal(&ret, "SecurityGroupReferences", "SecurityGroupReference")
return ret, errors.Wrapf(err, "resp.Unmarshal")
}
func (self *SRegion) GetSecurityGroups(vpcId, name string, securityGroupIds []string, offset int, limit int) ([]SSecurityGroup, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
+11 -2
View File
@@ -38,10 +38,10 @@ func init() {
return nil
})
type SecurityGroupShowOptions struct {
type SecurityGroupIdOptions struct {
ID string `help:"ID or name of security group"`
}
shellutils.R(&SecurityGroupShowOptions{}, "security-group-show", "Show details of a security group", func(cli *aliyun.SRegion, args *SecurityGroupShowOptions) error {
shellutils.R(&SecurityGroupIdOptions{}, "security-group-show", "Show details of a security group", func(cli *aliyun.SRegion, args *SecurityGroupIdOptions) error {
secgrp, err := cli.GetSecurityGroupDetails(args.ID)
if err != nil {
return err
@@ -50,6 +50,15 @@ func init() {
return nil
})
shellutils.R(&SecurityGroupIdOptions{}, "security-group-references", "Show references of a security group", func(cli *aliyun.SRegion, args *SecurityGroupIdOptions) error {
references, err := cli.DescribeSecurityGroupReferences(args.ID)
if err != nil {
return err
}
printList(references, 0, 0, 0, nil)
return nil
})
type SecurityGroupCreateOptions struct {
NAME string `help:"SecurityGroup name"`
VpcId string `help:"VPC ID"`
+40
View File
@@ -136,6 +136,46 @@ func (self *SecurityGroupPolicy) String() string {
return strings.Join(result, ";")
}
type ReferredSecurityGroup struct {
SecurityGroupId string
ReferredSecurityGroupIds []string
}
func (self *SSecurityGroup) GetReferences() ([]cloudprovider.SecurityGroupReference, error) {
references, err := self.region.DescribeSecurityGroupReferences(self.SecurityGroupId)
if err != nil {
return nil, errors.Wrapf(err, "DescribeSecurityGroupReferences")
}
ret := []cloudprovider.SecurityGroupReference{}
for _, refer := range references {
if refer.SecurityGroupId == self.SecurityGroupId {
for _, id := range refer.ReferredSecurityGroupIds {
ret = append(ret, cloudprovider.SecurityGroupReference{
Id: id,
})
}
}
}
return ret, nil
}
func (self *SRegion) DescribeSecurityGroupReferences(id string) ([]ReferredSecurityGroup, error) {
params := map[string]string{
"Region": self.Region,
"SecurityGroupIds.0": id,
}
resp, err := self.vpcRequest("DescribeSecurityGroupReferences", params)
if err != nil {
return nil, errors.Wrapf(err, "DescribeSecurityGroupReferences")
}
ret := []ReferredSecurityGroup{}
err = resp.Unmarshal(&ret, "ReferredSecurityGroupSet")
if err != nil {
return nil, errors.Wrapf(err, "resp.Unmarshal")
}
return ret, nil
}
func (self *SecurityGroupPolicy) toRules() []cloudprovider.SecurityRule {
result := []cloudprovider.SecurityRule{}
rule := cloudprovider.SecurityRule{
@@ -55,6 +55,15 @@ func init() {
return cloudprovider.ErrNotFound
})
shellutils.R(&SecurityGroupOptions{}, "security-group-references", "Show references of a security group", func(cli *qcloud.SRegion, args *SecurityGroupOptions) error {
references, err := cli.DescribeSecurityGroupReferences(args.ID)
if err != nil {
return err
}
printList(references, 0, 0, 0, nil)
return nil
})
shellutils.R(&SecurityGroupOptions{}, "security-group-delete", "Delete SecurityGroup", func(cli *qcloud.SRegion, args *SecurityGroupOptions) error {
return cli.DeleteSecurityGroup(args.ID)
})
+6
View File
@@ -14,6 +14,12 @@
package multicloud
import "yunion.io/x/onecloud/pkg/cloudprovider"
type SSecurityGroup struct {
SVirtualResourceBase
}
func (self *SSecurityGroup) GetReferences() ([]cloudprovider.SecurityGroupReference, error) {
return []cloudprovider.SecurityGroupReference{}, nil
}