| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410 |
- // 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"
- "fmt"
- "strings"
- "time"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/gotypes"
- "yunion.io/x/pkg/util/compare"
- "yunion.io/x/pkg/util/rbacscope"
- "yunion.io/x/pkg/util/regutils"
- "yunion.io/x/pkg/util/secrules"
- "yunion.io/x/pkg/utils"
- "yunion.io/x/sqlchemy"
- "yunion.io/x/onecloud/pkg/apis"
- api "yunion.io/x/onecloud/pkg/apis/compute"
- "yunion.io/x/onecloud/pkg/cloudcommon/consts"
- "yunion.io/x/onecloud/pkg/cloudcommon/db"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
- "yunion.io/x/onecloud/pkg/cloudcommon/policy"
- "yunion.io/x/onecloud/pkg/cloudcommon/validators"
- "yunion.io/x/onecloud/pkg/compute/options"
- "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/stringutils2"
- )
- // +onecloud:swagger-gen-model-singular=secgroup
- // +onecloud:swagger-gen-model-plural=secgroups
- type SSecurityGroupManager struct {
- db.SSharableVirtualResourceBaseManager
- db.SExternalizedResourceBaseManager
- SManagedResourceBaseManager
- SCloudregionResourceBaseManager
- SVpcResourceBaseManager
- SGlobalVpcResourceBaseManager
- }
- var SecurityGroupManager *SSecurityGroupManager
- func init() {
- SecurityGroupManager = &SSecurityGroupManager{
- SSharableVirtualResourceBaseManager: db.NewSharableVirtualResourceBaseManager(
- SSecurityGroup{},
- "secgroups_tbl",
- "secgroup",
- "secgroups",
- ),
- }
- SecurityGroupManager.NameLength = 128
- SecurityGroupManager.SetVirtualObject(SecurityGroupManager)
- }
- const (
- SECURITY_GROUP_SEPARATOR = ";"
- )
- type SSecurityGroup struct {
- db.SSharableVirtualResourceBase
- db.SExternalizedResourceBase
- IsDirty bool `nullable:"false" default:"false"`
- SManagedResourceBase
- SCloudregionResourceBase `width:"36" charset:"ascii" nullable:"false" list:"domain" create:"domain_required" default:"default"`
- SGlobalVpcResourceBase `width:"36" charset:"ascii" list:"user" create:"domain_optional" json:"globalvpc_id"`
- SVpcResourceBase `wdith:"36" charset:"ascii" nullable:"true" list:"domain" create:"domain_optional" update:""`
- }
- func (self *SSecurityGroup) GetCloudproviderId() string {
- return self.ManagerId
- }
- // 安全组列表
- func (manager *SSecurityGroupManager) ListItemFilter(
- ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- input api.SecgroupListInput,
- ) (*sqlchemy.SQuery, error) {
- var err error
- q, err = manager.SSharableVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, input.SharableVirtualResourceListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SSharableVirtualResourceBaseManager.ListItemFilter")
- }
- q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, input.ExternalizedResourceBaseListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
- }
- q, err = manager.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, input.ManagedResourceListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemFilter")
- }
- q, err = manager.SCloudregionResourceBaseManager.ListItemFilter(ctx, q, userCred, input.RegionalFilterListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemFilter")
- }
- if len(input.VpcId) > 0 {
- vpcObj, err := validators.ValidateModel(ctx, userCred, VpcManager, &input.VpcId)
- if err != nil {
- return nil, err
- }
- vpc := vpcObj.(*SVpc)
- region, err := vpc.GetRegion()
- if err != nil {
- return nil, err
- }
- filter, err := region.GetDriver().GetSecurityGroupFilter(vpc)
- if err != nil {
- return nil, err
- }
- q = filter(q)
- }
- serverStr := input.ServerId
- if len(serverStr) > 0 {
- guest, _, err := ValidateGuestResourceInput(ctx, userCred, input.ServerResourceInput)
- if err != nil {
- return nil, errors.Wrap(err, "ValidateGuestResourceInput")
- }
- serverId := guest.GetId()
- filters := []sqlchemy.ICondition{}
- filters = append(filters, sqlchemy.In(q.Field("id"), GuestManager.Query("secgrp_id").Equals("id", serverId).SubQuery()))
- filters = append(filters, sqlchemy.In(q.Field("id"), GuestsecgroupManager.Query("secgroup_id").Equals("guest_id", serverId).SubQuery()))
- isAdmin := false
- // admin := (input.Admin != nil && *input.Admin)
- allowScope, _ := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList)
- if allowScope == rbacscope.ScopeSystem || allowScope == rbacscope.ScopeDomain {
- isAdmin = true
- }
- if isAdmin {
- filters = append(filters, sqlchemy.In(q.Field("id"), GuestManager.Query("admin_secgrp_id").Equals("id", serverId).SubQuery()))
- }
- q = q.Filter(sqlchemy.OR(filters...))
- }
- if len(input.DBInstanceId) > 0 {
- _, err = validators.ValidateModel(ctx, userCred, DBInstanceManager, &input.DBInstanceId)
- if err != nil {
- return nil, err
- }
- sq := DBInstanceSecgroupManager.Query("secgroup_id").Equals("dbinstance_id", input.DBInstanceId)
- q = q.In("id", sq.SubQuery())
- }
- if len(input.LoadbalancerId) > 0 {
- _, err = validators.ValidateModel(ctx, userCred, LoadbalancerManager, &input.LoadbalancerId)
- if err != nil {
- return nil, err
- }
- sq := LoadbalancerSecurityGroupManager.Query("secgroup_id").Equals("loadbalancer_id", input.LoadbalancerId)
- q = q.In("id", sq.SubQuery())
- }
- if len(input.ElasticcacheId) > 0 {
- _, err = validators.ValidateModel(ctx, userCred, ElasticcacheManager, &input.ElasticcacheId)
- if err != nil {
- return nil, err
- }
- sq := ElasticcachesecgroupManager.Query("secgroup_id").Equals("elasticcache_id", input.ElasticcacheId).Distinct()
- q = q.In("id", sq.SubQuery())
- }
- if len(input.Ip) > 0 || len(input.Ports) > 0 {
- sq := SecurityGroupRuleManager.Query("secgroup_id")
- if len(input.Ip) > 0 {
- sq = sq.Like("cidr", input.Ip+"%")
- }
- if len(input.Ports) > 0 {
- sq = sq.Equals("ports", input.Ports)
- }
- if utils.IsInStringArray(input.Direction, []string{"in", "out"}) {
- sq = sq.Equals("direction", input.Direction)
- }
- q = q.In("id", sq.SubQuery())
- }
- if input.CloudEnv == "onpremise" {
- q = q.IsNullOrEmpty("manager_id")
- }
- return q, nil
- }
- func (manager *SSecurityGroupManager) OrderByExtraFields(
- ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- input api.SecgroupListInput,
- ) (*sqlchemy.SQuery, error) {
- var err error
- q, err = manager.SSharableVirtualResourceBaseManager.OrderByExtraFields(ctx, q, userCred, input.SharableVirtualResourceListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SSharableVirtualResourceBaseManager.OrderByExtraFields")
- }
- orderByGuest := input.OrderByGuestCnt
- 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 (manager *SSecurityGroupManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
- var err error
- q, err = manager.SSharableVirtualResourceBaseManager.QueryDistinctExtraField(q, field)
- if err == nil {
- return q, nil
- }
- q, err = manager.SVpcResourceBaseManager.QueryDistinctExtraField(q, field)
- if err == nil {
- return q, nil
- }
- q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraField(q, field)
- if err == nil {
- return q, nil
- }
- q, err = manager.SCloudregionResourceBaseManager.QueryDistinctExtraField(q, field)
- if err == nil {
- return q, nil
- }
- q, err = manager.SGlobalVpcResourceBaseManager.QueryDistinctExtraField(q, field)
- if err == nil {
- return q, nil
- }
- return q, httperrors.ErrNotFound
- }
- func (manager *SSecurityGroupManager) QueryDistinctExtraFields(q *sqlchemy.SQuery, resource string, fields []string) (*sqlchemy.SQuery, error) {
- var err error
- q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraFields(q, resource, fields)
- if err == nil {
- return q, nil
- }
- return q, httperrors.ErrNotFound
- }
- func (self *SSecurityGroup) GetChangeOwnerCandidateDomainIds() []string {
- candidates := [][]string{}
- vpc, _ := self.GetVpc()
- if vpc != nil {
- candidates = append(candidates, vpc.GetChangeOwnerCandidateDomainIds())
- }
- return db.ISharableMergeChangeOwnerCandidateDomainIds(self, candidates...)
- }
- 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_POD, 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) 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) getDesc() *api.SecgroupJsonDesc {
- return &api.SecgroupJsonDesc{
- Id: self.Id,
- Name: self.Name,
- }
- }
- func (self *SSecurityGroup) ClearRuleDirty() error {
- _, err := sqlchemy.GetDB().Exec(
- fmt.Sprintf(
- "update %s set is_dirty = false where secgroup_id = ?",
- SecurityGroupRuleManager.TableSpec().Name(),
- ), self.Id,
- )
- return err
- }
- func (manager *SSecurityGroupManager) FetchCustomizeColumns(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- query jsonutils.JSONObject,
- objs []interface{},
- fields stringutils2.SSortedStrings,
- isList bool,
- ) []api.SecgroupDetails {
- rows := make([]api.SecgroupDetails, len(objs))
- virtRows := manager.SSharableVirtualResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- managerRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- regionRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- vpcRows := manager.SVpcResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- globalVpcRows := manager.SGlobalVpcResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- secgroupIds := make([]string, len(objs))
- secgroups := make([]*SSecurityGroup, len(objs))
- for i := range rows {
- rows[i] = api.SecgroupDetails{
- SharableVirtualResourceDetails: virtRows[i],
- VpcResourceInfo: vpcRows[i],
- GlobalVpcResourceInfo: globalVpcRows[i],
- }
- rows[i].ManagedResourceInfo = managerRows[i]
- rows[i].CloudregionResourceInfo = regionRows[i]
- secgroup := objs[i].(*SSecurityGroup)
- secgroupIds[i] = secgroup.Id
- secgroups[i] = secgroup
- }
- guests := []SGuest{}
- q := GuestManager.Query().IsFalse("pending_deleted")
- q = q.Filter(sqlchemy.OR(
- sqlchemy.In(q.Field("secgrp_id"), secgroupIds),
- sqlchemy.In(q.Field("admin_secgrp_id"), secgroupIds),
- ))
- ownerId, queryScope, err, _ := db.FetchCheckQueryOwnerScope(ctx, userCred, query, GuestManager, policy.PolicyActionList, true)
- if err != nil {
- log.Errorf("FetchCheckQueryOwnerScope error: %v", err)
- return rows
- }
- q = GuestManager.FilterByOwner(ctx, q, GuestManager, userCred, ownerId, queryScope)
- err = db.FetchModelObjects(GuestManager, q, &guests)
- if err != nil {
- log.Errorf("db.FetchModelObjects error: %v", err)
- return rows
- }
- adminGuestMaps := map[string]int{}
- systemGuestMaps := map[string]int{}
- normalGuestMaps := map[string]int{}
- guestNetworkMaps := map[string]int{}
- for i := range guests {
- if guests[i].IsSystem {
- if _, ok := systemGuestMaps[guests[i].SecgrpId]; !ok {
- systemGuestMaps[guests[i].SecgrpId] = 0
- }
- systemGuestMaps[guests[i].SecgrpId]++
- } else {
- if _, ok := normalGuestMaps[guests[i].SecgrpId]; !ok {
- normalGuestMaps[guests[i].SecgrpId] = 0
- }
- normalGuestMaps[guests[i].SecgrpId]++
- }
- if len(guests[i].AdminSecgrpId) > 0 {
- if _, ok := adminGuestMaps[guests[i].AdminSecgrpId]; !ok {
- adminGuestMaps[guests[i].AdminSecgrpId] = 0
- }
- adminGuestMaps[guests[i].AdminSecgrpId]++
- }
- }
- sq := GuestManager.Query("id").IsFalse("pending_deleted")
- sq = GuestManager.FilterByOwner(ctx, sq, GuestManager, userCred, ownerId, queryScope)
- guestSecgroups := []SGuestsecgroup{}
- q = GuestsecgroupManager.Query().In("secgroup_id", secgroupIds).In("guest_id", sq.SubQuery())
- err = db.FetchModelObjects(GuestsecgroupManager, q, &guestSecgroups)
- if err != nil {
- log.Errorf("db.FetchModelObjects error: %v", err)
- return rows
- }
- for i := range guestSecgroups {
- if _, ok := normalGuestMaps[guestSecgroups[i].SecgroupId]; !ok {
- normalGuestMaps[guestSecgroups[i].SecgroupId] = 0
- }
- normalGuestMaps[guestSecgroups[i].SecgroupId]++
- }
- rules := []SSecurityGroupRule{}
- q = SecurityGroupRuleManager.Query().In("secgroup_id", secgroupIds)
- err = db.FetchModelObjects(SecurityGroupRuleManager, q, &rules)
- if err != nil {
- log.Errorf("db.FetchModelObjects error: %v", err)
- return rows
- }
- gnq := GuestnetworksecgroupManager.Query()
- gq := GuestManager.Query().IsFalse("pending_deleted").SubQuery()
- gnq = gnq.Join(gq, sqlchemy.Equals(gnq.Field("guest_id"), gq.Field("id")))
- guestNetworkSecgroups := []SGuestnetworksecgroup{}
- err = db.FetchModelObjects(GuestnetworksecgroupManager, gnq, &guestNetworkSecgroups)
- if err != nil {
- log.Errorf("db.FetchModelObjects error: %v", err)
- return rows
- }
- for i := range guestNetworkSecgroups {
- if _, ok := guestNetworkMaps[guestNetworkSecgroups[i].SecgroupId]; !ok {
- guestNetworkMaps[guestNetworkSecgroups[i].SecgroupId] = 0
- }
- guestNetworkMaps[guestNetworkSecgroups[i].SecgroupId]++
- }
- totalCnt, err := manager.TotalCnt(secgroupIds)
- if err != nil {
- return rows
- }
- for i := range rows {
- rows[i].GuestCnt, _ = normalGuestMaps[secgroupIds[i]]
- rows[i].AdminGuestCnt, _ = adminGuestMaps[secgroupIds[i]]
- rows[i].SystemGuestCnt, _ = systemGuestMaps[secgroupIds[i]]
- rows[i].GuestNicCnt, _ = guestNetworkMaps[secgroupIds[i]]
- if cnt, ok := totalCnt[secgroupIds[i]]; ok {
- rows[i].TotalCnt = cnt.TotalCnt
- rows[i].LoadbalancerCnt = cnt.LoadbalancerCnt
- rows[i].RedisCnt = cnt.RedisCnt
- rows[i].RdsCnt = cnt.RdsCnt
- }
- }
- return rows
- }
- func (manager *SSecurityGroupManager) ValidateCreateData(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- ownerId mcclient.IIdentityProvider,
- query jsonutils.JSONObject,
- input *api.SSecgroupCreateInput,
- ) (*api.SSecgroupCreateInput, error) {
- if len(input.VpcId) == 0 {
- input.VpcId = api.DEFAULT_VPC_ID
- }
- vpcObj, err := validators.ValidateModel(ctx, userCred, VpcManager, &input.VpcId)
- if err != nil {
- return nil, err
- }
- vpc := vpcObj.(*SVpc)
- input.CloudproviderId = vpc.ManagerId
- input.CloudregionId = vpc.CloudregionId
- input.GlobalvpcId = vpc.GlobalvpcId
- region, err := vpc.GetRegion()
- if err != nil {
- return nil, err
- }
- driver := region.GetDriver()
- input, err = driver.ValidateCreateSecurityGroupInput(ctx, userCred, input)
- if err != nil {
- return nil, err
- }
- input.SharableVirtualResourceCreateInput, err = manager.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.SharableVirtualResourceCreateInput)
- if err != nil {
- return input, err
- }
- pendingUsage := SProjectQuota{Secgroup: 1}
- quotaKey := quotas.OwnerIdProjectQuotaKeys(rbacscope.ScopeProject, ownerId)
- pendingUsage.SetKeys(quotaKey)
- err = quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage)
- if err != nil {
- return input, httperrors.NewOutOfQuotaError("%s", err)
- }
- return 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)
- quota := &SProjectQuota{Secgroup: 1}
- quota.SetKeys(self.GetQuotaKeys())
- err := quotas.CancelPendingUsage(ctx, userCred, quota, quota, true)
- if err != nil {
- log.Errorf("Secgroup CancelPendingUsage fail %s", err)
- }
- input := &api.SSecgroupCreateInput{}
- data.Unmarshal(input)
- self.StartSecurityGroupCreateTask(ctx, userCred, input.Rules, "")
- }
- func (self *SSecurityGroup) StartSecurityGroupCreateTask(ctx context.Context, userCred mcclient.TokenCredential, rules []api.SSecgroupRuleCreateInput, parentTaskId string) error {
- params := jsonutils.NewDict()
- params.Set("rules", jsonutils.Marshal(rules))
- self.SetStatus(ctx, userCred, apis.STATUS_CREATING, "")
- task, err := taskman.TaskManager.NewTask(ctx, "SecurityGroupCreateTask", self, userCred, params, parentTaskId, "", nil)
- if err != nil {
- return errors.Wrapf(err, "NewTask")
- }
- return task.ScheduleRun(nil)
- }
- 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 secgrp.(*SSecurityGroup), nil
- }
- func (self *SSecurityGroup) GetSecurityRules() ([]SSecurityGroupRule, error) {
- q := SecurityGroupRuleManager.Query().Equals("secgroup_id", self.Id).Desc("priority")
- rules := []SSecurityGroupRule{}
- err := db.FetchModelObjects(SecurityGroupRuleManager, q, &rules)
- if err != nil {
- return nil, errors.Wrapf(err, "db.FetchModelObjects")
- }
- return rules, nil
- }
- func (self *SSecurityGroup) getSecurityRuleString() (string, error) {
- secgrouprules, err := self.GetSecurityRules()
- if err != nil {
- return "", errors.Wrapf(err, "getSecurityRules()")
- }
- var rules []string
- for _, rule := range secgrouprules {
- rules = append(rules, rule.String())
- }
- return strings.Join(rules, SECURITY_GROUP_SEPARATOR), nil
- }
- func totalSecurityGroupCount(scope rbacscope.TRbacScope, ownerId mcclient.IIdentityProvider) (int, error) {
- q := SecurityGroupManager.Query()
- switch scope {
- case rbacscope.ScopeSystem:
- // do nothing
- case rbacscope.ScopeDomain:
- q = q.Equals("domain_id", ownerId.GetProjectDomainId())
- case rbacscope.ScopeProject:
- q = q.Equals("tenant_id", ownerId.GetProjectId())
- }
- return q.CountWithError()
- }
- func (self *SSecurityGroup) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.SecurityGroupSyncstatusInput) (jsonutils.JSONObject, error) {
- if !self.IsManaged() {
- return nil, self.SetStatus(ctx, userCred, api.SECGROUP_STATUS_READY, "")
- }
- return nil, self.StartSecurityGroupSyncTask(ctx, userCred, "")
- }
- func (self *SSecurityGroup) StartSecurityGroupSyncTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
- params := jsonutils.NewDict()
- self.SetStatus(ctx, userCred, apis.STATUS_SYNC_STATUS, "")
- task, err := taskman.TaskManager.NewTask(ctx, "SecurityGroupSyncTask", self, userCred, params, parentTaskId, "", nil)
- if err != nil {
- return errors.Wrapf(err, "NewTask")
- }
- return task.ScheduleRun(nil)
- }
- func (self *SSecurityGroup) StartSecurityGroupRuleCreateTask(ctx context.Context, userCred mcclient.TokenCredential, ruleId, parentTaskId string) error {
- params := jsonutils.NewDict()
- params.Set("rule_id", jsonutils.NewString(ruleId))
- task, err := taskman.TaskManager.NewTask(ctx, "SecurityGroupRuleCreateTask", self, userCred, params, parentTaskId, "", nil)
- if err != nil {
- return errors.Wrapf(err, "NewTask")
- }
- return task.ScheduleRun(nil)
- }
- func (self *SSecurityGroup) StartSecurityGroupRuleDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, ruleId, parentTaskId string) error {
- params := jsonutils.NewDict()
- params.Set("rule_id", jsonutils.NewString(ruleId))
- task, err := taskman.TaskManager.NewTask(ctx, "SecurityGroupRuleDeleteTask", self, userCred, params, parentTaskId, "", nil)
- if err != nil {
- return errors.Wrapf(err, "NewTask")
- }
- return task.ScheduleRun(nil)
- }
- func (self *SSecurityGroup) PerformAddRule(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
- secgrouprule := &SSecurityGroupRule{}
- secgrouprule.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("%v", err)
- }
- if err := rule.ValidateRule(); err != nil {
- return nil, httperrors.NewInputParameterError("%v", err)
- }
- if err := SecurityGroupRuleManager.TableSpec().Insert(ctx, secgrouprule); err != nil {
- return nil, httperrors.NewInputParameterError("%v", err)
- }
- self.DoSync(ctx, userCred)
- return nil, nil
- }
- func (self *SSecurityGroup) PerformClone(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SecurityGroupCloneInput) (api.SecurityGroupCloneInput, error) {
- if len(input.Name) == 0 {
- return input, httperrors.NewMissingParameterError("name")
- }
- ownerId := &db.SOwnerId{
- DomainId: userCred.GetProjectDomainId(),
- ProjectId: userCred.GetProjectId(),
- }
- pendingUsage := SProjectQuota{Secgroup: 1}
- quotaKey := quotas.OwnerIdProjectQuotaKeys(rbacscope.ScopeProject, ownerId)
- pendingUsage.SetKeys(quotaKey)
- err := quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage)
- if err != nil {
- return input, httperrors.NewOutOfQuotaError("%s", err)
- }
- secgroup := &SSecurityGroup{}
- secgroup.SetModelManager(SecurityGroupManager, secgroup)
- secgroup.Name = input.Name
- secgroup.Description = input.Description
- secgroup.Status = api.SECGROUP_STATUS_READY
- secgroup.ProjectId = userCred.GetProjectId()
- secgroup.DomainId = userCred.GetProjectDomainId()
- err = func() error {
- lockman.LockClass(ctx, SecurityGroupManager, "name")
- defer lockman.ReleaseClass(ctx, SecurityGroupManager, "name")
- input.Name, err = db.GenerateName(ctx, SecurityGroupManager, ownerId, input.Name)
- if err != nil {
- return err
- }
- return SecurityGroupManager.TableSpec().Insert(ctx, secgroup)
- }()
- if err != nil {
- return input, httperrors.NewGeneralError(errors.Wrapf(err, "Insert"))
- }
- secgrouprules, err := self.GetSecurityRules()
- if err != nil {
- return input, httperrors.NewGeneralError(errors.Wrapf(err, "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(ctx, secgrouprule); err != nil {
- return input, err
- }
- }
- quota := &SProjectQuota{Secgroup: 1}
- quota.SetKeys(secgroup.GetQuotaKeys())
- err = quotas.CancelPendingUsage(ctx, userCred, quota, quota, true)
- if err != nil {
- log.Errorf("Secgroup CancelPendingUsage fail %s", err)
- }
- logclient.AddActionLogWithContext(ctx, secgroup, logclient.ACT_CREATE, secgroup.GetShortDesc(ctx), userCred, true)
- return input, nil
- }
- /*func (self *SSecurityGroup) GetAllowList() (secrules.SecurityRuleSet, secrules.SecurityRuleSet, error) {
- in := secrules.SecurityRuleSet{}
- out := secrules.SecurityRuleSet{}
- rules, err := self.GetSecurityRules()
- if err != nil {
- return in, out, errors.Wrapf(err, "GetSecRules")
- }
- for i := range rules {
- r, _ := rules[i].toRule()
- if rules[i].Direction == secrules.DIR_IN {
- in = append(in, *r)
- } else {
- out = append(out, *r)
- }
- }
- in = append(in, *secrules.MustParseSecurityRule("in:deny any"))
- out = append(out, *secrules.MustParseSecurityRule("out:allow any"))
- return in.AllowList(), out.AllowList(), nil
- }*/
- func (self *SSecurityGroup) clearRules() error {
- _, err := sqlchemy.GetDB().Exec(
- fmt.Sprintf(
- "delete from %s where secgroup_id = ?",
- SecurityGroupRuleManager.TableSpec().Name(),
- ), self.Id,
- )
- return err
- }
- 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)
- 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 {
- guests, err := secgrp.GetKvmGuests()
- if err != nil {
- return errors.Wrapf(err, "GetKvmGuests")
- }
- for _, guest := range guests {
- guest.StartSyncTask(ctx, userCred, true, "")
- }
- }
- return nil
- }
- 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(context.Background(), userCred, self.Id)
- })
- }
- func (manager *SSecurityGroupManager) InitializeData() error {
- _, err := manager.FetchById(api.SECGROUP_DEFAULT_ID)
- if err != nil && err != sql.ErrNoRows {
- return errors.Wrapf(err, `manager.FetchById("default")`)
- }
- if errors.Cause(err) == sql.ErrNoRows {
- log.Debugf("Init default secgroup")
- secGrp := &SSecurityGroup{}
- secGrp.SetModelManager(manager, secGrp)
- secGrp.Id = api.SECGROUP_DEFAULT_ID
- secGrp.Name = "Default"
- secGrp.Status = api.SECGROUP_STATUS_READY
- secGrp.ProjectId = auth.AdminCredential().GetProjectId()
- secGrp.DomainId = auth.AdminCredential().GetProjectDomainId()
- // secGrp.IsEmulated = false
- secGrp.IsPublic = true
- secGrp.Deleted = false
- secGrp.PublicScope = string(rbacscope.ScopeSystem)
- err = manager.TableSpec().InsertOrUpdate(context.TODO(), secGrp)
- if err != nil {
- return errors.Wrapf(err, "Insert default secgroup")
- }
- defRule := SSecurityGroupRule{}
- defRule.SetModelManager(SecurityGroupRuleManager, &defRule)
- defRule.Direction = secrules.DIR_IN
- defRule.Protocol = secrules.PROTO_ANY
- defRule.Priority = 1
- // empty CIDR means ::/0 or 0.0.0.0/0
- defRule.CIDR = "" // "0.0.0.0/0"
- defRule.Action = string(secrules.SecurityRuleAllow)
- defRule.SecgroupId = api.SECGROUP_DEFAULT_ID
- err = SecurityGroupRuleManager.TableSpec().Insert(context.TODO(), &defRule)
- if err != nil {
- return errors.Wrapf(err, "Insert default secgroup rule")
- }
- }
- guests := make([]SGuest, 0)
- q := GuestManager.Query().Equals("hypervisor", api.HYPERVISOR_KVM).IsNotEmpty("external_id").IsNullOrEmpty("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 = api.SECGROUP_DEFAULT_ID
- return nil
- })
- }
- return nil
- }
- func (manager *SSecurityGroupManager) PerformClean(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
- q := SecurityGroupManager.Query()
- q = q.Filter(
- sqlchemy.AND(
- sqlchemy.Equals(q.Field("cloudregion_id"), api.DEFAULT_REGION_ID),
- sqlchemy.NotEquals(q.Field("id"), api.SECGROUP_DEFAULT_ID),
- sqlchemy.NotIn(q.Field("id"), GuestManager.Query("secgrp_id").IsNotNull("secgrp_id").SubQuery()),
- sqlchemy.NotIn(q.Field("id"), GuestManager.Query("admin_secgrp_id").IsNotNull("admin_secgrp_id").SubQuery()),
- sqlchemy.NotIn(q.Field("id"), GuestsecgroupManager.Query("secgroup_id").IsNotNull("secgroup_id").SubQuery()),
- sqlchemy.NotIn(q.Field("id"), GuestsecgroupManager.Query("secgroup_id").IsNotNull("secgroup_id").SubQuery()),
- sqlchemy.NotIn(q.Field("id"), DBInstanceSecgroupManager.Query("secgroup_id").IsNotNull("secgroup_id").SubQuery()),
- sqlchemy.NotIn(q.Field("id"), ElasticcachesecgroupManager.Query("secgroup_id").IsNotNull("secgroup_id").SubQuery()),
- sqlchemy.NotIn(q.Field("id"), LoadbalancerSecurityGroupManager.Query("secgroup_id").IsNotNull("secgroup_id").SubQuery()),
- ),
- )
- secgroups := []SSecurityGroup{}
- err := db.FetchModelObjects(SecurityGroupManager, q, &secgroups)
- if err != nil {
- return nil, errors.Wrapf(err, "FetchModelObjects")
- }
- for i := range secgroups {
- err = secgroups[i].RealDelete(ctx, userCred)
- if err != nil {
- return nil, errors.Wrapf(err, "delete %s", secgroups[i].Name)
- }
- }
- return nil, nil
- }
- func (self *SSecurityGroup) GetRegionDriver() (IRegionDriver, error) {
- if len(self.ManagerId) > 0 {
- manager, err := self.GetCloudprovider()
- if err != nil {
- return nil, errors.Wrapf(err, "GetCloudprovider")
- }
- return GetRegionDriver(manager.Provider), nil
- }
- return GetRegionDriver(api.CLOUD_PROVIDER_ONECLOUD), nil
- }
- func (self *SSecurityGroup) GetRegion() (*SCloudregion, error) {
- regionObj, err := CloudregionManager.FetchById(self.CloudregionId)
- if err != nil {
- return nil, errors.Wrapf(err, "FetchById")
- }
- return regionObj.(*SCloudregion), nil
- }
- func (self *SSecurityGroup) GetGlobalVpc() (*SGlobalVpc, error) {
- vpc, err := GlobalVpcManager.FetchById(self.GlobalvpcId)
- if err != nil {
- return nil, err
- }
- return vpc.(*SGlobalVpc), nil
- }
- func (self *SSecurityGroup) GetISecurityGroup(ctx context.Context) (cloudprovider.ICloudSecurityGroup, error) {
- if len(self.ExternalId) == 0 {
- return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty external id")
- }
- // google
- if len(self.GlobalvpcId) > 0 {
- vpc, err := self.GetGlobalVpc()
- if err != nil {
- return nil, errors.Wrapf(err, "GetGlobalVpc")
- }
- iVpc, err := vpc.GetICloudGlobalVpc(ctx)
- if err != nil {
- return nil, errors.Wrapf(err, "GetICloudGlobalVpc")
- }
- securityGroups, err := iVpc.GetISecurityGroups()
- if err != nil {
- return nil, errors.Wrapf(err, "GetISecurityGroups")
- }
- for i := range securityGroups {
- if securityGroups[i].GetGlobalId() == self.ExternalId {
- return securityGroups[i], nil
- }
- }
- return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%v", self.ExternalId)
- }
- iRegion, err := self.GetIRegion(ctx)
- if err != nil {
- return nil, errors.Wrapf(err, "GetIRegion")
- }
- return iRegion.GetISecurityGroupById(self.ExternalId)
- }
- func (self *SSecurityGroup) GetIRegion(ctx context.Context) (cloudprovider.ICloudRegion, error) {
- region, err := self.GetRegion()
- if err != nil {
- return nil, errors.Wrapf(err, "GetRegion")
- }
- provider, err := self.GetProvider(ctx)
- if err != nil {
- return nil, errors.Wrapf(err, "GetProvider")
- }
- return provider.GetIRegionById(region.ExternalId)
- }
- func (self *SSecurityGroup) GetCloudprovider() (*SCloudprovider, error) {
- providerObj, err := CloudproviderManager.FetchById(self.ManagerId)
- if err != nil {
- return nil, errors.Wrapf(err, "FetchById")
- }
- return providerObj.(*SCloudprovider), nil
- }
- func (self *SSecurityGroup) GetProvider(ctx context.Context) (cloudprovider.ICloudProvider, error) {
- manager, err := self.GetCloudprovider()
- if err != nil {
- return nil, errors.Wrapf(err, "GetProvider")
- }
- return manager.GetProvider(ctx)
- }
- 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)
- g4SQ := sm.query(GuestnetworksecgroupManager, "secgroup_id", "guest4", secIds)
- rdsSQ := sm.query(DBInstanceSecgroupManager, "secgroup_id", "rds", secIds)
- redisSQ := sm.query(ElasticcachesecgroupManager, "secgroup_id", "redis", secIds)
- lbSQ := sm.query(LoadbalancerSecurityGroupManager, "secgroup_id", "loadbalancer", 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")),
- sqlchemy.SUM("loadbalancer_cnt", lbSQ.Field("loadbalancer")),
- sqlchemy.SUM("guest_nic_cnt", g4SQ.Field("guest4")),
- )
- 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.LeftJoin(lbSQ, sqlchemy.Equals(secQ.Field("id"), lbSQ.Field("secgroup_id")))
- secQ = secQ.LeftJoin(g4SQ, sqlchemy.Equals(secQ.Field("id"), g4SQ.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 nil, errors.Wrapf(err, "secQ.All")
- }
- 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
- }
- return result, nil
- }
- func (self *SSecurityGroup) ValidateDeleteCondition(ctx context.Context, info api.SecgroupDetails) error {
- if self.Id == options.Options.DefaultSecurityGroupId {
- return httperrors.NewProtectedResourceError("not allow to delete default security group")
- }
- if self.Id == options.Options.DefaultSecurityGroupIdForKvm {
- return httperrors.NewProtectedResourceError("not allow to delete default security group for kvm")
- }
- if self.Id == options.Options.DefaultSecurityGroupIdForContainer {
- return httperrors.NewProtectedResourceError("not allow to delete default security group for container")
- }
- if self.Id == options.Options.DefaultAdminSecurityGroupId {
- return httperrors.NewProtectedResourceError("not allow to delete default admin security group")
- }
- if self.Id == options.Options.DefaultAdminSecurityGroupIdForKvm {
- return httperrors.NewProtectedResourceError("not allow to delete default admin security group for kvm")
- }
- if self.Id == options.Options.DefaultAdminSecurityGroupIdForContainer {
- return httperrors.NewProtectedResourceError("not allow to delete default admin security group for container")
- }
- if info.TotalCnt > 0 {
- return httperrors.NewNotEmptyError("the security group %s is in use cnt: %d", self.Id, info.TotalCnt)
- }
- return self.SSharableVirtualResourceBase.ValidateDeleteCondition(ctx, nil)
- }
- func (self *SSecurityGroup) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
- return self.StartDeleteSecurityGroupTask(ctx, userCred, "")
- }
- func (self *SSecurityGroup) StartDeleteSecurityGroupTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
- params := jsonutils.NewDict()
- self.SetStatus(ctx, userCred, apis.STATUS_DELETING, "")
- task, err := taskman.TaskManager.NewTask(ctx, "SecurityGroupDeleteTask", self, userCred, params, parentTaskId, "", nil)
- if err != nil {
- return errors.Wrapf(err, "NewTask")
- }
- return task.ScheduleRun(nil)
- }
- func (self *SSecurityGroup) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
- log.Infof("do nothing for delete secgroup")
- return nil
- }
- func (self *SSecurityGroup) OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential) {
- if len(self.ExternalId) == 0 || options.Options.KeepTagLocalization {
- return
- }
- if account := self.GetCloudaccount(); account != nil && account.ReadOnly {
- return
- }
- err := self.StartRemoteUpdateTask(ctx, userCred, true, "")
- if err != nil {
- log.Errorf("StartRemoteUpdateTask fail: %s", err)
- }
- }
- func (self *SSecurityGroup) StartRemoteUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, replaceTags bool, parentTaskId string) error {
- data := jsonutils.NewDict()
- data.Set("replace_tags", jsonutils.NewBool(replaceTags))
- task, err := taskman.TaskManager.NewTask(ctx, "SecurityGroupRemoteUpdateTask", self, userCred, data, parentTaskId, "", nil)
- if err != nil {
- return errors.Wrap(err, "RemoteUpdateTask")
- }
- self.SetStatus(ctx, userCred, apis.STATUS_UPDATE_TAGS, "StartRemoteUpdateTask")
- return task.ScheduleRun(nil)
- }
- func (self *SSecurityGroup) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
- rules := []SSecurityGroupRule{}
- q := SecurityGroupRuleManager.Query().Equals("secgroup_id", self.Id)
- err := db.FetchModelObjects(SecurityGroupRuleManager, q, &rules)
- if err != nil {
- return errors.Wrap(err, "db.FetchModelObjects")
- }
- for i := 0; i < len(rules); i++ {
- lockman.LockObject(ctx, &rules[i])
- defer lockman.ReleaseObject(ctx, &rules[i])
- err := rules[i].RealDelete(ctx, userCred)
- if err != nil {
- return errors.Wrap(err, "rules[i].Delete")
- }
- }
- return self.SVirtualResourceBase.Delete(ctx, userCred)
- }
- func (sg *SSecurityGroup) GetQuotaKeys() quotas.IQuotaKeys {
- return quotas.OwnerIdProjectQuotaKeys(rbacscope.ScopeProject, sg.GetOwnerId())
- }
- func (sg *SSecurityGroup) GetUsages() []db.IUsage {
- if sg.PendingDeleted || sg.Deleted {
- return nil
- }
- usage := SProjectQuota{Secgroup: 1}
- keys := sg.GetQuotaKeys()
- usage.SetKeys(keys)
- return []db.IUsage{
- &usage,
- }
- }
- func (self *SSecurityGroup) PerformImportRules(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SecgroupImportRulesInput) (jsonutils.JSONObject, error) {
- for i := range input.Rules {
- if input.Rules[i].Priority == nil {
- return nil, httperrors.NewMissingParameterError("priority")
- }
- err := input.Rules[i].Check()
- if err != nil {
- return nil, httperrors.NewInputParameterError("rule %d is invalid: %s", i+1, err)
- }
- }
- for _, r := range input.Rules {
- rule := &SSecurityGroupRule{
- Priority: int(*r.Priority),
- Protocol: r.Protocol,
- Ports: r.Ports,
- Direction: r.Direction,
- CIDR: r.CIDR,
- Action: r.Action,
- Description: r.Description,
- }
- rule.SecgroupId = self.Id
- err := SecurityGroupRuleManager.TableSpec().Insert(ctx, rule)
- if err != nil {
- return nil, httperrors.NewGeneralError(errors.Wrapf(err, "Insert rule"))
- }
- }
- return nil, nil
- }
- func (manager *SSecurityGroupManager) ListItemExportKeys(ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- keys stringutils2.SSortedStrings,
- ) (*sqlchemy.SQuery, error) {
- q, err := manager.SSharableVirtualResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
- if err != nil {
- return nil, errors.Wrap(err, "SSharableVirtualResourceBaseManager.ListItemExportKeys")
- }
- if keys.ContainsAny(manager.SCloudregionResourceBaseManager.GetExportKeys()...) {
- q, err = manager.SCloudregionResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
- if err != nil {
- return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemExportKeys")
- }
- }
- if keys.ContainsAny(manager.SManagedResourceBaseManager.GetExportKeys()...) {
- q, err = manager.SManagedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
- if err != nil {
- return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemExportKeys")
- }
- }
- if keys.ContainsAny(manager.SGlobalVpcResourceBaseManager.GetExportKeys()...) {
- q, err = manager.SGlobalVpcResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
- if err != nil {
- return nil, errors.Wrap(err, "SGlobalVpcResourceBaseManager.ListItemExportKeys")
- }
- }
- if keys.ContainsAny(manager.SVpcResourceBaseManager.GetExportKeys()...) {
- q, err = manager.SVpcResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
- if err != nil {
- return nil, errors.Wrap(err, "SVpcResourceBaseManager.ListItemExportKeys")
- }
- }
- return q, nil
- }
- func (self *SCloudregion) GetSecgroups(managerId, vpcId string) ([]SSecurityGroup, error) {
- q := SecurityGroupManager.Query().Equals("cloudregion_id", self.Id).Equals("manager_id", managerId)
- if len(vpcId) > 0 {
- q = q.Equals("vpc_id", vpcId)
- }
- ret := []SSecurityGroup{}
- return ret, db.FetchModelObjects(SecurityGroupManager, q, &ret)
- }
- func (self *SCloudregion) SyncSecgroups(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, vpc *SVpc, exts []cloudprovider.ICloudSecurityGroup, xor bool) compare.SyncResult {
- vpcId := ""
- if !gotypes.IsNil(vpc) {
- vpcId = vpc.Id
- }
- key := fmt.Sprintf("%s-%s", self.Id, vpcId)
- lockman.LockRawObject(ctx, SecurityGroupManager.Keyword(), key)
- defer lockman.ReleaseRawObject(ctx, SecurityGroupManager.Keyword(), key)
- result := compare.SyncResult{}
- dbSecs, err := self.GetSecgroups(provider.Id, vpcId)
- if err != nil {
- result.Error(err)
- return result
- }
- syncOwnerId := provider.GetOwnerId()
- removed := make([]SSecurityGroup, 0)
- commondb := make([]SSecurityGroup, 0)
- commonext := make([]cloudprovider.ICloudSecurityGroup, 0)
- added := make([]cloudprovider.ICloudSecurityGroup, 0)
- err = compare.CompareSets(dbSecs, exts, &removed, &commondb, &commonext, &added)
- if err != nil {
- result.Error(err)
- return result
- }
- for i := 0; i < len(removed); i += 1 {
- err = removed[i].RealDelete(ctx, userCred)
- if err != nil {
- result.DeleteError(err)
- continue
- }
- result.Delete()
- }
- for i := 0; i < len(commondb); i += 1 {
- if !xor {
- err = commondb[i].SyncWithCloudSecurityGroup(ctx, userCred, commonext[i], syncOwnerId, true)
- if err != nil {
- result.UpdateError(err)
- continue
- }
- }
- result.Update()
- }
- for i := 0; i < len(added); i += 1 {
- err := self.newFromCloudSecurityGroup(ctx, userCred, provider, vpc, added[i], syncOwnerId)
- if err != nil {
- result.AddError(err)
- continue
- }
- result.Add()
- }
- return result
- }
- func (self *SSecurityGroup) SyncWithCloudSecurityGroup(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- ext cloudprovider.ICloudSecurityGroup,
- syncOwnerId mcclient.IIdentityProvider,
- syncRule bool,
- ) error {
- _, err := db.Update(self, func() error {
- self.Name = ext.GetName()
- if len(self.Description) == 0 {
- self.Description = ext.GetDescription()
- }
- return nil
- })
- if err != nil {
- return errors.Wrapf(err, "db.Update")
- }
- if account := self.GetCloudaccount(); account != nil {
- syncVirtualResourceMetadata(ctx, userCred, self, ext, account.ReadOnly)
- }
- if provider, _ := self.GetCloudprovider(); provider != nil {
- SyncCloudProject(ctx, userCred, self, syncOwnerId, ext, provider)
- }
- if !syncRule {
- return nil
- }
- rules, err := ext.GetRules()
- if err != nil {
- return errors.Wrapf(err, "GetRules")
- }
- result := self.SyncRules(ctx, userCred, rules)
- if result.IsError() {
- logclient.AddSimpleActionLog(self, logclient.ACT_CLOUD_SYNC, result, userCred, false)
- }
- return nil
- }
- func (self *SSecurityGroup) GetSecurityGroups(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- ownerId mcclient.IIdentityProvider,
- filter func(q *sqlchemy.SQuery) *sqlchemy.SQuery,
- ) ([]SSecurityGroup, error) {
- query := SecurityGroupManager.Query().Equals("status", api.SECGROUP_STATUS_READY).IsNotEmpty("external_id")
- query = filter(query)
- query = query.Filter(
- sqlchemy.OR(
- sqlchemy.AND(
- sqlchemy.Equals(query.Field("public_scope"), "system"),
- sqlchemy.Equals(query.Field("is_public"), true),
- ),
- sqlchemy.AND(
- sqlchemy.Equals(query.Field("tenant_id"), ownerId.GetProjectId()),
- sqlchemy.Equals(query.Field("domain_id"), ownerId.GetDomainId()),
- ),
- ),
- )
- ret := []SSecurityGroup{}
- return ret, db.FetchModelObjects(SecurityGroupManager, query, &ret)
- }
- func (self *SCloudregion) newFromCloudSecurityGroup(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- provider *SCloudprovider,
- vpc *SVpc,
- ext cloudprovider.ICloudSecurityGroup,
- syncOwnerId mcclient.IIdentityProvider,
- ) error {
- ret := &SSecurityGroup{}
- ret.SetModelManager(SecurityGroupManager, ret)
- ret.Name = ext.GetName()
- ret.CloudregionId = self.Id
- if vpc != nil {
- ret.VpcId = vpc.Id
- }
- ret.Description = ext.GetDescription()
- ret.ExternalId = ext.GetGlobalId()
- ret.ManagerId = provider.Id
- ret.Status = api.SECGROUP_STATUS_READY
- err := SecurityGroupManager.TableSpec().Insert(ctx, ret)
- if err != nil {
- return errors.Wrapf(err, "Insert")
- }
- syncVirtualResourceMetadata(ctx, userCred, ret, ext, false)
- SyncCloudProject(ctx, userCred, ret, syncOwnerId, ext, provider)
- rules, err := ext.GetRules()
- if err != nil {
- return errors.Wrapf(err, "GetRules")
- }
- result := ret.SyncRules(ctx, userCred, rules)
- if result.IsError() {
- logclient.AddSimpleActionLog(ret, logclient.ACT_CLOUD_SYNC, result, userCred, false)
- }
- return nil
- }
|