Files
cloudpods/pkg/compute/models/secgroups.go
T
wanyaoqi a59e171bf5 feature:
- postpaid server support expire
- extend distinct tenant filed
- gpu batch perform action
2019-10-10 12:04:22 +08:00

741 lines
24 KiB
Go

// 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 models
import (
"context"
"database/sql"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SSecurityGroupManager struct {
db.SSharableVirtualResourceBaseManager
}
var SecurityGroupManager *SSecurityGroupManager
func init() {
SecurityGroupManager = &SSecurityGroupManager{
SSharableVirtualResourceBaseManager: db.NewSharableVirtualResourceBaseManager(
SSecurityGroup{},
"secgroups_tbl",
"secgroup",
"secgroups",
),
}
SecurityGroupManager.NameLength = 128
SecurityGroupManager.NameRequireAscii = true
SecurityGroupManager.SetVirtualObject(SecurityGroupManager)
}
const (
SECURITY_GROUP_SEPARATOR = ";"
)
type SSecurityGroup struct {
db.SSharableVirtualResourceBase
IsDirty bool `nullable:"false" default:"false"` // Column(Boolean, nullable=False, default=False)
}
func (manager *SSecurityGroupManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
equalSecgroup, _ := query.GetString("equals")
if len(equalSecgroup) > 0 {
_secgroup, err := manager.FetchByIdOrName(userCred, equalSecgroup)
if err != nil {
return nil, httperrors.NewInputParameterError("Failed fetching secgroup %s", equalSecgroup)
}
secgroup := _secgroup.(*SSecurityGroup)
sq := manager.Query().NotEquals("id", secgroup.Id)
secgroups := []SSecurityGroup{}
err = db.FetchModelObjects(manager, sq, &secgroups)
if err != nil {
return nil, err
}
srs := secgroup.getSecurityGroupRuleSet()
secgroupIds := []string{}
for i := 0; i < len(secgroups); i++ {
if srs.IsEqual(secgroups[i].getSecurityGroupRuleSet()) {
secgroupIds = append(secgroupIds, secgroups[i].Id)
}
}
q = q.In("id", secgroupIds)
}
return q, nil
}
func (manager *SSecurityGroupManager) OrderByExtraFields(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
q, err := manager.SVirtualResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query)
if err != nil {
return nil, err
}
orderByCache, _ := query.GetString("order_by_cache_cnt")
if sqlchemy.SQL_ORDER_ASC.Equals(orderByCache) || sqlchemy.SQL_ORDER_DESC.Equals(orderByCache) {
caches := SecurityGroupCacheManager.Query().SubQuery()
cacheQ := caches.Query(
caches.Field("secgroup_id"),
sqlchemy.COUNT("cache_cnt"),
)
cacheSQ := cacheQ.GroupBy(caches.Field("secgroup_id")).SubQuery()
q = q.LeftJoin(cacheSQ, sqlchemy.Equals(q.Field("id"), cacheSQ.Field("secgroup_id")))
if sqlchemy.SQL_ORDER_ASC.Equals(orderByCache) {
q = q.Asc(cacheSQ.Field("cache_cnt"))
} else {
q = q.Desc(cacheSQ.Field("cache_cnt"))
}
}
orderByGuest, _ := query.GetString("order_by_guest_cnt")
if sqlchemy.SQL_ORDER_ASC.Equals(orderByGuest) || sqlchemy.SQL_ORDER_DESC.Equals(orderByGuest) {
guests := GuestManager.Query().SubQuery()
guestsecgroups := GuestsecgroupManager.Query().SubQuery()
q1 := guests.Query(guests.Field("id").Label("guest_id"),
guests.Field("secgrp_id").Label("secgroup_id"))
q2 := guestsecgroups.Query(guestsecgroups.Field("guest_id"),
guestsecgroups.Field("secgroup_id"))
uq := sqlchemy.Union(q1, q2)
uQ := uq.Query(
uq.Field("secgroup_id"),
sqlchemy.COUNT("guest_cnt", uq.Field("guest_id")),
)
sq := uQ.GroupBy(uq.Field("secgroup_id")).SubQuery()
q = q.LeftJoin(sq, sqlchemy.Equals(q.Field("id"), sq.Field("secgroup_id")))
if sqlchemy.SQL_ORDER_ASC.Equals(orderByGuest) {
q = q.Asc(sq.Field("guest_cnt"))
} else {
q = q.Desc(sq.Field("guest_cnt"))
}
}
return q, nil
}
func (self *SSecurityGroup) GetGuestsQuery() *sqlchemy.SQuery {
guests := GuestManager.Query().SubQuery()
return guests.Query().Filter(
sqlchemy.OR(
sqlchemy.Equals(guests.Field("secgrp_id"), self.Id),
sqlchemy.Equals(guests.Field("admin_secgrp_id"), self.Id),
sqlchemy.In(guests.Field("id"), GuestsecgroupManager.Query("guest_id").Equals("secgroup_id", self.Id).SubQuery()),
),
).Filter(sqlchemy.NotIn(guests.Field("hypervisor"), []string{api.HYPERVISOR_CONTAINER, api.HYPERVISOR_BAREMETAL, api.HYPERVISOR_ESXI}))
}
func (self *SSecurityGroup) GetGuestsCount() (int, error) {
return self.GetGuestsQuery().CountWithError()
}
func (self *SSecurityGroup) GetGuests() []SGuest {
guests := []SGuest{}
q := self.GetGuestsQuery()
err := db.FetchModelObjects(GuestManager, q, &guests)
if err != nil {
log.Errorf("GetGuests fail %s", err)
return nil
}
return guests
}
func (self *SSecurityGroup) GetSecgroupCacheQuery() *sqlchemy.SQuery {
return SecurityGroupCacheManager.Query().Equals("secgroup_id", self.Id)
}
func (self *SSecurityGroup) GetSecgroupCacheCount() (int, error) {
return self.GetSecgroupCacheQuery().CountWithError()
}
func (self *SSecurityGroup) getDesc() jsonutils.JSONObject {
desc := jsonutils.NewDict()
desc.Add(jsonutils.NewString(self.Name), "name")
desc.Add(jsonutils.NewString(self.Id), "id")
//desc.Add(jsonutils.NewString(self.getSecurityRuleString("")), "security_rules")
return desc
}
func (self *SSecurityGroup) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
extra, err := self.SSharableVirtualResourceBase.GetExtraDetails(ctx, userCred, query)
if err != nil {
return nil, err
}
extra.Add(jsonutils.NewInt(int64(len(self.GetGuests()))), "guest_cnt")
cnt, _ := self.GetSecgroupCacheCount()
extra.Add(jsonutils.NewInt(int64(cnt)), "cache_cnt")
extra.Add(jsonutils.NewString(self.getSecurityRuleString("")), "rules")
extra.Add(jsonutils.NewString(self.getSecurityRuleString("in")), "in_rules")
extra.Add(jsonutils.NewString(self.getSecurityRuleString("out")), "out_rules")
return extra, nil
}
func (self *SSecurityGroup) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SSharableVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query)
extra.Add(jsonutils.NewInt(int64(len(self.GetGuests()))), "guest_cnt")
cnt, _ := self.GetSecgroupCacheCount()
extra.Add(jsonutils.NewInt(int64(cnt)), "cache_cnt")
extra.Add(jsonutils.NewTimeString(self.CreatedAt), "created_at")
extra.Add(jsonutils.NewString(self.Description), "description")
return extra
}
func (manager *SSecurityGroupManager) ValidateCreateData(
ctx context.Context,
userCred mcclient.TokenCredential,
ownerId mcclient.IIdentityProvider,
query jsonutils.JSONObject,
data *jsonutils.JSONDict,
) (*jsonutils.JSONDict, error) {
// TODO: check set pending quota
input := &api.SSecgroupCreateInput{}
err := data.Unmarshal(input)
if err != nil {
return nil, httperrors.NewInputParameterError("Failed to unmarshal input: %v", err)
}
for i, rule := range input.Rules {
err = rule.Check()
if err != nil {
return nil, httperrors.NewInputParameterError("rule %d is invalid: %s", i, err)
}
}
data, err = manager.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
if err != nil {
return nil, err
}
return input.JSON(input), nil
}
func (self *SSecurityGroup) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.SSharableVirtualResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
input := &api.SSecgroupCreateInput{}
data.Unmarshal(input)
for _, r := range input.Rules {
rule := &SSecurityGroupRule{
Priority: int64(r.Priority),
Protocol: r.Protocol,
Ports: r.Ports,
Direction: r.Direction,
CIDR: r.CIDR,
Action: r.Action,
Description: r.Description,
SecgroupID: self.Id,
}
SecurityGroupRuleManager.TableSpec().Insert(rule)
}
}
func (manager *SSecurityGroupManager) FetchSecgroupById(secId string) *SSecurityGroup {
if len(secId) > 0 {
secgrp, _ := manager.FetchById(secId)
if secgrp != nil {
return secgrp.(*SSecurityGroup)
}
}
return nil
}
func (self *SSecurityGroup) getSecurityRules(direction string) (rules []SSecurityGroupRule) {
secgrouprules := SecurityGroupRuleManager.Query().SubQuery()
sql := secgrouprules.Query().Filter(sqlchemy.Equals(secgrouprules.Field("secgroup_id"), self.Id)).Desc("priority")
if len(direction) > 0 && utils.IsInStringArray(direction, []string{"in", "out"}) {
sql = sql.Equals("direction", direction)
}
if err := db.FetchModelObjects(SecurityGroupRuleManager, sql, &rules); err != nil {
log.Errorf("GetGuests fail %s", err)
return
}
return
}
func (self *SSecurityGroup) GetSecRules(direction string) []secrules.SecurityRule {
rules := make([]secrules.SecurityRule, 0)
for _, _rule := range self.getSecurityRules(direction) {
//这里没必要拆分为单个单个的端口,到公有云那边适配
rule, err := _rule.toRule()
if err != nil {
log.Errorln(err)
continue
}
rules = append(rules, *rule)
}
return rules
}
func (self *SSecurityGroup) getSecurityRuleString(direction string) string {
secgrouprules := self.getSecurityRules(direction)
var rules []string
for _, rule := range secgrouprules {
rules = append(rules, rule.String())
}
return strings.Join(rules, SECURITY_GROUP_SEPARATOR)
}
func totalSecurityGroupCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider) (int, error) {
q := SecurityGroupManager.Query()
switch scope {
case rbacutils.ScopeSystem:
// do nothing
case rbacutils.ScopeDomain:
q = q.Equals("domain_id", ownerId.GetProjectDomainId())
case rbacutils.ScopeProject:
q = q.Equals("tenant_id", ownerId.GetProjectId())
}
return q.CountWithError()
}
func (self *SSecurityGroup) AllowPerformAddRule(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "add-rule")
}
func (self *SSecurityGroup) PerformAddRule(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
secgrouprule := &SSecurityGroupRule{SecgroupID: self.Id}
secgrouprule.SetModelManager(SecurityGroupRuleManager, secgrouprule)
if err := data.Unmarshal(secgrouprule); err != nil {
return nil, err
}
if len(secgrouprule.CIDR) > 0 {
if !regutils.MatchCIDR(secgrouprule.CIDR) && !regutils.MatchIPAddr(secgrouprule.CIDR) {
return nil, httperrors.NewInputParameterError("invalid ip address: %s", secgrouprule.CIDR)
}
} else {
secgrouprule.CIDR = "0.0.0.0/0"
}
rule := secrules.SecurityRule{
Priority: int(secgrouprule.Priority),
Direction: secrules.TSecurityRuleDirection(secgrouprule.Direction),
Action: secrules.TSecurityRuleAction(secgrouprule.Action),
Protocol: secgrouprule.Protocol,
Ports: []int{},
PortStart: -1,
PortEnd: -1,
}
if err := rule.ParsePorts(secgrouprule.Ports); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
if err := rule.ValidateRule(); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
if err := SecurityGroupRuleManager.TableSpec().Insert(secgrouprule); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
self.DoSync(ctx, userCred)
return nil, nil
}
func (self *SSecurityGroup) AllowPerformClone(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return true
}
func (self *SSecurityGroup) PerformClone(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
name, _ := data.GetString("name")
if len(name) == 0 {
return nil, httperrors.NewMissingParameterError("name")
}
_, err := SecurityGroupManager.FetchByName(userCred, name)
if err != nil {
if err != sql.ErrNoRows {
return nil, httperrors.NewInternalServerError("FetchByName fail %s", err)
}
} else {
return nil, httperrors.NewDuplicateNameError("name", name)
}
secgroup := &SSecurityGroup{}
secgroup.SetModelManager(SecurityGroupManager, secgroup)
secgroup.Name = name
secgroup.Description, _ = data.GetString("description")
secgroup.ProjectId = userCred.GetProjectId()
secgroup.DomainId = userCred.GetProjectDomainId()
err = SecurityGroupManager.TableSpec().Insert(secgroup)
if err != nil {
return nil, err
//db.OpsLog.LogCloneEvent(self, secgroup, userCred, nil)
}
secgrouprules := self.getSecurityRules("")
for _, rule := range secgrouprules {
secgrouprule := &SSecurityGroupRule{}
secgrouprule.SetModelManager(SecurityGroupRuleManager, secgrouprule)
secgrouprule.Priority = rule.Priority
secgrouprule.Protocol = rule.Protocol
secgrouprule.Ports = rule.Ports
secgrouprule.Direction = rule.Direction
secgrouprule.CIDR = rule.CIDR
secgrouprule.Action = rule.Action
secgrouprule.Description = rule.Description
secgrouprule.SecgroupID = secgroup.Id
if err := SecurityGroupRuleManager.TableSpec().Insert(secgrouprule); err != nil {
return nil, err
}
}
logclient.AddActionLogWithContext(ctx, secgroup, logclient.ACT_CREATE, secgroup.GetShortDesc(ctx), userCred, true)
return nil, nil
}
func (self *SSecurityGroup) AllowPerformUnion(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "union")
}
func (self *SSecurityGroup) PerformUnion(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
secgroupIds := jsonutils.GetQueryStringArray(data, "secgroups")
if len(secgroupIds) == 0 {
return nil, httperrors.NewMissingParameterError("secgroups")
}
srs := self.getSecurityGroupRuleSet()
secgroups := []*SSecurityGroup{}
for _, secgroupId := range secgroupIds {
_secgroup, err := SecurityGroupManager.FetchByIdOrName(userCred, secgroupId)
if err != nil {
return nil, httperrors.NewResourceNotFoundError("failed to find secgroup %s error: %v", secgroupId, err)
}
secgroup := _secgroup.(*SSecurityGroup)
secgroup.SetModelManager(SecurityGroupManager, secgroup)
_srs := secgroup.getSecurityGroupRuleSet()
if !srs.IsEqual(_srs) {
return nil, httperrors.NewUnsupportOperationError("secgroup %s rules not equals %s rules", secgroup.Name, self.Name)
}
secgroups = append(secgroups, secgroup)
}
for i := 0; i < len(secgroups); i++ {
secgroup := secgroups[i]
if err := self.migrateSecurityGroupCache(secgroup); err != nil {
return nil, err
}
if err := self.migrateGuestSecurityGroup(secgroup); err != nil {
return nil, err
}
secgroup.RealDelete(ctx, userCred)
}
self.DoSync(ctx, userCred)
return nil, nil
}
func (self *SSecurityGroup) getSecurityGroupRuleSet() secrules.SecurityGroupRuleSet {
rules := self.GetSecRules("")
srs := secrules.SecurityGroupRuleSet{}
for i := 0; i < len(rules); i++ {
srs.AddRule(rules[i])
}
return srs
}
func (self *SSecurityGroup) migrateSecurityGroupCache(secgroup *SSecurityGroup) error {
caches := []SSecurityGroupCache{}
q := SecurityGroupCacheManager.Query().Equals("secgroup_id", secgroup.Id)
err := db.FetchModelObjects(SecurityGroupCacheManager, q, &caches)
if err != nil {
return err
}
for i := 0; i < len(caches); i++ {
cache := caches[i]
_, err := db.Update(&cache, func() error {
cache.SecgroupId = self.Id
return nil
})
if err != nil {
return err
}
}
return nil
}
func (self *SSecurityGroup) migrateGuestSecurityGroup(secgroup *SSecurityGroup) error {
guests := secgroup.GetGuests()
for i := 0; i < len(guests); i++ {
guest := guests[i]
_, err := db.Update(&guest, func() error {
if guest.SecgrpId == secgroup.Id {
guest.SecgrpId = self.Id
}
if guest.AdminSecgrpId == secgroup.Id {
guest.AdminSecgrpId = self.Id
}
return nil
})
if err != nil {
return err
}
}
guestsecgroups, err := GuestsecgroupManager.GetGuestSecgroups(nil, secgroup)
if err != nil {
return err
}
for i := 0; i < len(guestsecgroups); i++ {
guestsecgroup := guestsecgroups[i]
_, err := db.Update(&guestsecgroup, func() error {
guestsecgroup.SecgroupId = self.Id
return nil
})
if err != nil {
return err
}
}
return nil
}
func (manager *SSecurityGroupManager) getSecurityGroups() ([]SSecurityGroup, error) {
secgroups := make([]SSecurityGroup, 0)
q := manager.Query()
if err := db.FetchModelObjects(manager, q, &secgroups); err != nil {
return nil, err
} else {
return secgroups, nil
}
}
func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*SSecurityGroup, error) {
srs := secrules.SecurityGroupRuleSet{}
rules, err := extSec.GetRules()
if err != nil {
return nil, err
}
for i := 0; i < len(rules); i++ {
srs.AddRule(rules[i])
}
// 查询所有共享或与provider在同一项目的安全组,比对寻找一个与云上安全组规则相同的安全组
secgroups := []SSecurityGroup{}
q := manager.Query()
q = q.Filter(
sqlchemy.OR(
sqlchemy.Equals(q.Field("tenant_id"), provider.ProjectId),
sqlchemy.AND(
sqlchemy.IsTrue(q.Field("is_public")),
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeSystem),
),
),
)
if err := db.FetchModelObjects(manager, q, &secgroups); err != nil {
log.Errorf("failed to fetch secgroups %v", err)
}
for _, secgroup := range secgroups {
_srs := secgroup.getSecurityGroupRuleSet()
if srs.IsEqual(_srs) {
return &secgroup, nil
}
}
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
secgroup := SSecurityGroup{}
secgroup.SetModelManager(manager, &secgroup)
newName, err := db.GenerateName(manager, userCred, extSec.GetName())
if err != nil {
return nil, err
}
secgroup.Name = newName
secgroup.Description = extSec.GetDescription()
secgroup.ProjectId = provider.ProjectId
secgroup.DomainId = provider.DomainId
if err := manager.TableSpec().Insert(&secgroup); err != nil {
return nil, err
}
//这里必须先同步下规则,不然下次对比此安全组规则为空
SecurityGroupRuleManager.SyncRules(ctx, userCred, &secgroup, rules)
db.OpsLog.LogEvent(&secgroup, db.ACT_CREATE, secgroup.GetShortDesc(ctx), userCred)
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
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 needSync {
for _, guest := range secgrp.GetGuests() {
guest.StartSyncTask(ctx, userCred, true, "")
}
}
}
}
func (self *SSecurityGroup) DoSync(ctx context.Context, userCred mcclient.TokenCredential) {
if _, err := db.Update(self, func() error {
self.IsDirty = true
return nil
}); err != nil {
log.Errorf("Update Security Group error: %s", err.Error())
}
time.AfterFunc(10*time.Second, func() {
SecurityGroupManager.DelaySync(ctx, userCred, self.Id)
})
}
func (manager *SSecurityGroupManager) InitializeData() error {
_, err := manager.FetchById("default")
if err != nil && err != sql.ErrNoRows {
log.Errorf("find default secgroup fail %s", err)
return err
}
if err == sql.ErrNoRows {
var secGrp *SSecurityGroup
secGrp = &SSecurityGroup{}
secGrp.SetModelManager(manager, secGrp)
secGrp.Id = "default"
secGrp.Name = "Default"
secGrp.ProjectId = auth.AdminCredential().GetProjectId()
secGrp.DomainId = auth.AdminCredential().GetProjectDomainId()
// secGrp.IsEmulated = false
secGrp.IsPublic = true
err = manager.TableSpec().Insert(secGrp)
if err != nil {
log.Errorf("Insert default secgroup failed!!! %s", err)
return err
}
defRule := SSecurityGroupRule{}
defRule.SetModelManager(SecurityGroupRuleManager, &defRule)
defRule.Direction = secrules.DIR_IN
defRule.Protocol = secrules.PROTO_ANY
defRule.Priority = 1
defRule.CIDR = "0.0.0.0/0"
defRule.Action = string(secrules.SecurityRuleAllow)
defRule.SecgroupID = "default"
err = SecurityGroupRuleManager.TableSpec().Insert(&defRule)
if err != nil {
log.Errorf("Insert default secgroup rule fail %s", err)
return err
}
}
guests := make([]SGuest, 0)
q := GuestManager.Query()
q = q.Filter(sqlchemy.OR(sqlchemy.IsEmpty(q.Field("secgrp_id")), sqlchemy.IsNull(q.Field("secgrp_id"))))
err = db.FetchModelObjects(GuestManager, q, &guests)
if err != nil {
log.Errorf("fetch guests without secgroup fail %s", err)
return err
}
for i := 0; i < len(guests); i += 1 {
db.Update(&guests[i], func() error {
guests[i].SecgrpId = "default"
return nil
})
}
return nil
}
func (self *SSecurityGroup) ValidateDeleteCondition(ctx context.Context) error {
cnt, err := self.GetGuestsCount()
if err != nil {
return httperrors.NewInternalServerError("GetGuestsCount fail %s", err)
}
if cnt > 0 {
return httperrors.NewNotEmptyError("the security group is in use")
}
if self.Id == "default" {
return httperrors.NewProtectedResourceError("not allow to delete default security group")
}
return self.SSharableVirtualResourceBase.ValidateDeleteCondition(ctx)
}
func (self *SSecurityGroup) GetSecurityGroupCaches() []SSecurityGroupCache {
caches := []SSecurityGroupCache{}
q := SecurityGroupCacheManager.Query()
q = q.Filter(sqlchemy.Equals(q.Field("secgroup_id"), self.Id))
if err := db.FetchModelObjects(SecurityGroupCacheManager, q, &caches); err != nil {
log.Errorf("get secgroupcache for secgroup %s error: %v", self.Name, err)
}
return caches
}
func (self *SSecurityGroup) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
return self.StartDeleteSecurityGroupTask(ctx, userCred, jsonutils.NewDict(), "")
}
func (self *SSecurityGroup) StartDeleteSecurityGroupTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
task, err := taskman.TaskManager.NewTask(ctx, "SecurityGroupDeleteTask", self, userCred, params, parentTaskId, "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
func (self *SSecurityGroup) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return self.SSharableVirtualResourceBase.DoPendingDelete(ctx, userCred)
}
func (self *SSecurityGroup) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
rules := []SSecurityGroupRule{}
q := SecurityGroupRuleManager.Query().Equals("secgroup_id", self.Id)
if err := db.FetchModelObjects(SecurityGroupRuleManager, q, &rules); err != nil {
log.Errorf("failed to fetch secgroup %s rules error: %v", self.Name, err)
return err
}
for i := 0; i < len(rules); i++ {
if err := rules[i].Delete(ctx, userCred); err != nil {
return err
}
}
return self.SVirtualResourceBase.Delete(ctx, userCred)
}