feat(region,host,vpcagent): allow guest network dedicate secgroups (#24263)

This commit is contained in:
wanyaoqi
2026-02-07 17:32:12 +08:00
committed by GitHub
parent 52df8590b0
commit f76bc53e90
27 changed files with 1191 additions and 77 deletions
+3
View File
@@ -36,4 +36,7 @@ func init() {
cmd.Perform("change-owner", &options.SecgroupChangeOwnerOptions{})
cmd.Perform("import-rules", &options.SecgroupImportRulesOptions{})
cmd.PerformClass("clean", &options.SecgroupCleanOptions{})
scmd := shell.NewResourceCmd(&modules.Servernetworksecgroups)
scmd.List(&options.ServerNetworkSecgroupListOptions{})
}
+3
View File
@@ -153,6 +153,9 @@ func init() {
cmd.Get("numa-info", new(options.ServerIdOptions))
cmd.BatchPerform("screen-dump", new(options.ServerIdsOptions))
cmd.Perform("set-network-num-queues", new(options.ServerSetNetworkNumQueues))
cmd.Perform("set-network-secgroup", new(options.ServerNetworkSecGroupsOptions))
cmd.Perform("add-network-secgroup", new(options.ServerNetworkSecGroupsOptions))
cmd.Perform("revoke-network-secgroup", new(options.ServerNetworkSecGroupsOptions))
cmd.GetProperty(&options.ServerStatusStatisticsOptions{})
cmd.GetProperty(&options.ServerProjectStatisticsOptions{})
+3
View File
@@ -130,6 +130,9 @@ type NetworkConfig struct {
Domain string `json:"domain_id"`
Ifname string `json:"ifname"`
Schedtags []*SchedtagConfig `json:"schedtags"`
// network secgroups
Secgroups []string `json:"secgroups"`
}
type AttachNetworkInput struct {
+19
View File
@@ -20,6 +20,8 @@ import (
"yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/onecloud/pkg/apis"
)
type GuestnetworkDetails struct {
@@ -82,6 +84,12 @@ type GuestnetworkShortDesc struct {
Index int `json:"index"`
}
type GuestnetworkSecgroupShortDesc struct {
NetworkIndex int `json:"network_index"`
Secgroups []apis.StandaloneShortDesc `json:"secgroups"`
Mac string `json:"mac"`
}
type GuestnetworkListInput struct {
GuestJointsListInput
@@ -148,6 +156,9 @@ type GuestnetworkBaseDesc struct {
WireId string `json:"wire_id"`
Interface string `json:"interface"`
Secgroups []*SecgroupJsonDesc `json:"secgroups"`
SecurityRules string `json:"security_rules"`
Vpc struct {
Id string `json:"id"`
Provider string `json:"provider"`
@@ -183,6 +194,14 @@ type GuestnetworkJsonDesc struct {
LinkUp bool `json:"link_up"`
}
type GuestnetworkSecgroupDesc struct {
Secgroups []*SecgroupJsonDesc `json:"secgroups"`
SecurityRules string `json:"security_rules"`
Index int `json:"index"`
Mac string `json:"mac"`
}
type SNicTrafficRecord struct {
RxTraffic int64 `json:"rx_traffic"`
TxTraffic int64 `json:"tx_traffic"`
+33 -3
View File
@@ -258,6 +258,9 @@ type ServerDetails struct {
// 关联主安全组
Secgroup string `json:"secgroup"`
// 网卡级别安全组
NetworkSecgroups []GuestnetworkSecgroupShortDesc `json:"network_secgroups"`
// 浮动IP
Eip string `json:"eip"`
// 浮动IP类型
@@ -573,12 +576,32 @@ type GuestSetSecgroupInput struct {
SecgroupIds []string `json:"secgroup_ids"`
}
type GuestSetNetworkSecgroupInput struct {
// 安全组Id列表
// 实例必须处于运行,休眠或者关机状态
SecgroupIds []string `json:"secgroup_ids"`
// 虚机网卡 index 或者 mac 地址
NetworkIndex *int `json:"network_index"`
MacAddr string `json:"mac_addr"`
}
type GuestRevokeSecgroupInput struct {
// 安全组Id列表
// 实例必须处于运行,休眠或者关机状态
SecgroupIds []string `json:"secgroup_ids"`
}
type GuestRevokeNetworkSecgroupInput struct {
// 安全组Id列表
// 实例必须处于运行,休眠或者关机状态
SecgroupIds []string `json:"secgroup_ids"`
// 虚机网卡 index 或者 mac 地址
NetworkIndex *int `json:"network_index"`
MacAddr string `json:"mac_addr"`
}
type GuestAssignSecgroupInput struct {
// 安全组Id
// 实例必须处于运行,休眠或者关机状态
@@ -608,6 +631,12 @@ type GuestAddSecgroupInput struct {
SecgroupIds []string `json:"secgroup_ids"`
}
type GuestNetworkAddSecgroupInput struct {
SecgroupIds []string `json:"secgroup_ids"`
NetworkIndex *int `json:"network_index"`
}
type ServerRemoteUpdateInput struct {
// 是否覆盖替换所有标签
ReplaceTags *bool `json:"replace_tags" help:"replace all remote tags"`
@@ -944,9 +973,10 @@ type GuestJsonDesc struct {
NetworkRoles []string `json:"network_roles"`
Secgroups []*SecgroupJsonDesc `json:"secgroups"`
SecurityRules string `json:"security_rules"`
AdminSecurityRules string `json:"admin_security_rules"`
Secgroups []*SecgroupJsonDesc `json:"secgroups"`
SecurityRules string `json:"security_rules"`
AdminSecurityRules string `json:"admin_security_rules"`
NicSecgroups []*GuestnetworkSecgroupDesc `json:"nic_secgroups"`
ExtraOptions jsonutils.JSONObject `json:"extra_options"`
+43 -1
View File
@@ -272,6 +272,9 @@ type SecgroupDetails struct {
// 关联云主机数量, 不包含回收站云主机
GuestCnt int `json:"guest_cnt,allowempty"`
// 关联云主机网卡数量, 不包含回收站云主机
GuestNicCnt int `json:"guest_nic_cnt,allowempty"`
// 关联此安全组的云主机is_system为true数量, , 不包含回收站云主机
SystemGuestCnt int `json:"system_guest_cnt,allowempty"`
@@ -310,6 +313,16 @@ type GuestsecgroupListInput struct {
SecgroupFilterListInput
}
type GuestnetworksecgroupListInput struct {
apis.ResourceBaseListInput
ServerFilterListInput
SecgroupFilterListInput
NetworkIndex *int `json:"network_index"`
IsAdmin bool `json:"is_admin"`
}
type ElasticcachesecgroupListInput struct {
ElasticcacheJointsListInput
SecgroupFilterListInput
@@ -324,6 +337,34 @@ type GuestsecgroupDetails struct {
Secgroup string `json:"secgroup"`
}
type GuestnetworksecgroupDetails struct {
GuestResourceInfo
SGuestsecgroup
SecurityGroupResourceInfo
ProjectId string `json:"tenant_id"`
apis.ProjectizedResourceInfo
// 安全组状态
SecgroupStatus string `json:"secgroup_status"`
// VPC ID
VpcId string `json:"vpc_id"`
Vpc string `json:"vpc"`
NetworkIndex int `json:"network_index"`
GuestNetwork string `json:"guest_network"`
MacAddr string `json:"mac_addr"`
Ifname string `json:"ifname"`
IpAddr string `json:"ip_addr"`
Ip6Addr string `json:"ip_6_addr"`
Admin bool `json:"admin"`
}
type ElasticcachesecgroupDetails struct {
ElasticcacheJointResourceDetails
@@ -353,11 +394,12 @@ type SSecurityGroupRef struct {
RdsCnt int `json:"rds_cnt"`
RedisCnt int `json:"redis_cnt"`
LoadbalancerCnt int `json:"loadbalancer_cnt"`
GuestNicCnt int `json:"guest_nic_cnt"`
TotalCnt int `json:"total_cnt"`
}
func (self *SSecurityGroupRef) Sum() {
self.TotalCnt = self.GuestCnt + self.AdminGuestCnt + self.RdsCnt + self.RedisCnt + self.LoadbalancerCnt
self.TotalCnt = self.GuestCnt + self.AdminGuestCnt + self.RdsCnt + self.RedisCnt + self.LoadbalancerCnt + self.GuestNicCnt
}
type SecurityGroupSyncstatusInput struct {
+2
View File
@@ -328,6 +328,8 @@ func ParseNetworkConfig(desc string, idx int) (*compute.NetworkConfig, error) {
}
netConfig.Addresses6[i] = addr6.String()
}
} else if strings.HasPrefix(p, "secgroups=") {
netConfig.Secgroups = strings.Split(p[len("secgroups="):], ",")
} else if p == "require_designated_ip" {
netConfig.RequireDesignatedIP = true
} else if p == "random_exit" {
+13
View File
@@ -3218,6 +3218,13 @@ func (self *SGuest) PerformAttachnetwork(
input.Nets[i].Driver = api.NETWORK_DRIVER_VFIO
isolatedDevCount += 1
}
if len(input.Nets[i].Secgroups) > 0 {
secgroupIds, err := isValidSecgroups(ctx, userCred, input.Nets[i].Secgroups)
if err != nil {
return nil, err
}
input.Nets[i].Secgroups = secgroupIds
}
if input.Nets[i].IsDefault {
defaultGwCnt++
}
@@ -3277,6 +3284,12 @@ func (self *SGuest) PerformAttachnetwork(
return nil, errors.Wrap(err, "self.allocSriovNicDevice")
}
}
if len(input.Nets[i].Secgroups) > 0 {
err = self.SaveNetworkSecgroups(ctx, userCred, input.Nets[i].Secgroups, gns[0].Index)
if err != nil {
return nil, errors.Wrap(err, "SaveNetworkSecgroups")
}
}
}
// adjust default gateway
+83
View File
@@ -206,6 +206,16 @@ func (manager *SGuestManager) FetchCustomizeColumns(
}
}
}
if len(fields) == 0 || fields.Contains("network_secgroups") {
gnss := fetchGuestNetworkSecgroups(guestIds)
if gnss != nil {
for i := range rows {
if gns, ok := gnss[guestIds[i]]; ok {
rows[i].NetworkSecgroups = gns
}
}
}
}
if len(fields) == 0 || fields.Contains("eip") || fields.Contains("eip_mode") {
geips := fetchGuestEips(guestIds)
if geips != nil {
@@ -759,6 +769,79 @@ func fetchSecgroups(guestIds []string) map[string][]apis.StandaloneShortDesc {
return ret
}
func fetchGuestNetworkSecgroups(guestIds []string) map[string][]api.GuestnetworkSecgroupShortDesc {
guestnetworks := GuestnetworkManager.Query().SubQuery()
guestnetworksecgroups := GuestnetworksecgroupManager.Query().SubQuery()
secgroups := SecurityGroupManager.Query().SubQuery()
q := guestnetworksecgroups.Query(
guestnetworksecgroups.Field("guest_id"),
guestnetworksecgroups.Field("network_index"),
guestnetworksecgroups.Field("secgroup_id"),
guestnetworks.Field("mac_addr").Label("mac"),
secgroups.Field("name").Label("secgroup_name"),
)
q = q.Join(guestnetworks, sqlchemy.AND(
sqlchemy.Equals(guestnetworks.Field("guest_id"), guestnetworksecgroups.Field("guest_id")),
sqlchemy.Equals(guestnetworks.Field("index"), guestnetworksecgroups.Field("network_index")),
))
q = q.Join(secgroups, sqlchemy.Equals(secgroups.Field("id"), guestnetworksecgroups.Field("secgroup_id")))
q = q.Filter(sqlchemy.In(guestnetworksecgroups.Field("guest_id"), guestIds))
type sGuestNetworkSecgroupInfo struct {
GuestId string
NetworkIndex int
SecgroupId string
SecgroupName string
Mac string
}
gnss := make([]sGuestNetworkSecgroupInfo, 0)
err := q.All(&gnss)
if err != nil && errors.Cause(err) != sql.ErrNoRows {
log.Errorf("fetchGuestNetworkSecgroups query error: %s", err)
return nil
}
groupedSecgroups := make(map[string][]sGuestNetworkSecgroupInfo)
for i := range gnss {
groupedSecgroup, ok := groupedSecgroups[gnss[i].GuestId]
if !ok {
groupedSecgroup = make([]sGuestNetworkSecgroupInfo, 0)
}
groupedSecgroups[gnss[i].GuestId] = append(groupedSecgroup, gnss[i])
}
ret := make(map[string][]api.GuestnetworkSecgroupShortDesc)
for guestId, secgroups := range groupedSecgroups {
networkGroupedSecgroups := make(map[int][]sGuestNetworkSecgroupInfo)
for i := range secgroups {
secgroupInfos, ok := networkGroupedSecgroups[secgroups[i].NetworkIndex]
if !ok {
secgroupInfos = make([]sGuestNetworkSecgroupInfo, 0)
}
networkGroupedSecgroups[secgroups[i].NetworkIndex] = append(secgroupInfos, secgroups[i])
}
guestnetworkSecgroups := make([]api.GuestnetworkSecgroupShortDesc, 0)
for networkIndex, secgroups := range networkGroupedSecgroups {
//networkSecgroupsDesc := make([]api.GuestnetworkSecgroupShortDesc, 0)
nsDesc := api.GuestnetworkSecgroupShortDesc{
NetworkIndex: networkIndex,
Mac: secgroups[0].Mac,
}
for i := range secgroups {
nsDesc.Secgroups = append(nsDesc.Secgroups, apis.StandaloneShortDesc{
Id: secgroups[i].SecgroupId,
Name: secgroups[i].SecgroupName,
})
}
guestnetworkSecgroups = append(guestnetworkSecgroups, nsDesc)
}
ret[guestId] = guestnetworkSecgroups
}
return ret
}
type sEipInfo struct {
IpAddr string
Mode string
+14
View File
@@ -414,3 +414,17 @@ func (guest *SGuest) RevokeAllSecgroups(ctx context.Context, userCred mcclient.T
}
return guest.saveDefaultSecgroupId(userCred, options.Options.GetDefaultSecurityGroupId(guest.Hypervisor), false)
}
func isValidSecgroups(ctx context.Context, userCred mcclient.TokenCredential, secgroups []string) ([]string, error) {
secGrpIds := []string{}
for _, secgroup := range secgroups {
secGrpObj, err := SecurityGroupManager.FetchByIdOrName(ctx, userCred, secgroup)
if err != nil {
return nil, httperrors.NewResourceNotFoundError("Secgroup %s not found", secgroup)
}
if !utils.IsInStringArray(secGrpObj.GetId(), secGrpIds) {
secGrpIds = append(secGrpIds, secGrpObj.GetId())
}
}
return secGrpIds, nil
}
+15
View File
@@ -741,6 +741,21 @@ func (gn *SGuestnetwork) getJsonDesc() *api.GuestnetworkJsonDesc {
return desc
}
func (gn *SGuestnetwork) getSecgroupDesc() *api.GuestnetworkSecgroupDesc {
secgroupJson, _ := GuestnetworksecgroupManager.getNetworkSecgroupJson(gn.GuestId, gn.Index)
if len(secgroupJson) == 0 {
return nil
}
guest := gn.GetGuest()
securityRules := guest.getNetworkSecurityGroupsRules(gn.Index)
return &api.GuestnetworkSecgroupDesc{
Secgroups: secgroupJson,
SecurityRules: securityRules,
Index: gn.Index,
Mac: gn.MacAddr,
}
}
func (gn *SGuestnetwork) IsSriovWithoutOffload() bool {
if gn.Driver != api.NETWORK_DRIVER_VFIO {
return false
+644
View File
@@ -0,0 +1,644 @@
// 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"
"fmt"
"path"
"strconv"
"gopkg.in/fatih/set.v0"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"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/validators"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
type SGuestnetworksecgroupManager struct {
db.SResourceBaseManager
SGuestResourceBaseManager
SSecurityGroupResourceBaseManager
SCloudregionResourceBaseManager
SManagedResourceBaseManager
SVpcResourceBaseManager
}
var GuestnetworksecgroupManager *SGuestnetworksecgroupManager
func init() {
db.InitManager(func() {
GuestnetworksecgroupManager = &SGuestnetworksecgroupManager{
SResourceBaseManager: db.NewResourceBaseManager(
SGuestnetworksecgroup{},
"guestnetworksecgroups_tbl",
"guestnetworksecgroup",
"guestnetworksecgroups",
),
}
GuestnetworksecgroupManager.SetVirtualObject(GuestnetworksecgroupManager)
})
}
type SGuestnetworksecgroup struct {
db.SResourceBase
RowId int64 `primary:"true" auto_increment:"true" list:"user"`
GuestId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"`
SSecurityGroupResourceBase `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
NetworkIndex int `nullable:"false" list:"user" update:"user"`
Admin bool `nullable:"false" default:"false" list:"user" create:"optional"`
}
func (manager *SGuestnetworksecgroupManager) GetSlaveFieldName() string {
return "secgroup_id"
}
func (self *SGuestnetworksecgroup) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return db.DeleteModel(ctx, userCred, self)
}
func (manager *SGuestnetworksecgroupManager) ListItemFilter(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.GuestnetworksecgroupListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SGuestResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ServerFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SGuestJointsManager.ListItemFilter")
}
q, err = manager.SSecurityGroupResourceBaseManager.ListItemFilter(ctx, q, userCred, query.SecgroupFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SSecurityGroupResourceBaseManager.ListItemFilter")
}
if query.NetworkIndex != nil {
q = q.Equals("network_index", *query.NetworkIndex)
}
if query.IsAdmin {
q = q.IsFalse("admin")
}
return q, nil
}
func (manager *SGuestnetworksecgroupManager) OrderByExtraFields(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.GuestnetworksecgroupListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SGuestResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ServerFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SGuestJointsManager.OrderByExtraFields")
}
q, err = manager.SSecurityGroupResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.SecgroupFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SSecurityGroupResourceBaseManager.OrderByExtraFields")
}
return q, nil
}
func (manager *SGuestnetworksecgroupManager) ListItemExportKeys(ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
keys stringutils2.SSortedStrings,
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SGuestResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
if err != nil {
return nil, errors.Wrap(err, "SGuestJointsManager.ListItemExportKeys")
}
if keys.ContainsAny(manager.SSecurityGroupResourceBaseManager.GetExportKeys()...) {
q, err = manager.SSecurityGroupResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
if err != nil {
return nil, errors.Wrap(err, "SSecurityGroupResourceBaseManager.ListItemExportKeys")
}
}
return q, nil
}
func (manager *SGuestnetworksecgroupManager) FetchCustomizeColumns(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
objs []interface{},
fields stringutils2.SSortedStrings,
isList bool,
) []api.GuestnetworksecgroupDetails {
rows := make([]api.GuestnetworksecgroupDetails, len(objs))
guestList := make([]interface{}, len(objs))
guestIds := make([]string, len(objs))
guestNetworkIdx := make([]int, len(objs))
secgrpIds := make([]string, len(objs))
for i := range objs {
secgrpIds[i] = objs[i].(*SGuestnetworksecgroup).SecgroupId
guestList[i] = &SGuestResourceBase{objs[i].(*SGuestnetworksecgroup).GuestId}
guestIds[i] = objs[i].(*SGuestnetworksecgroup).GuestId
guestNetworkIdx[i] = objs[i].(*SGuestnetworksecgroup).NetworkIndex
}
groups := make(map[string]SSecurityGroup)
err := db.FetchStandaloneObjectsByIds(SecurityGroupManager, secgrpIds, groups)
if err != nil {
log.Errorf("FetchStandaloneObjectsByIds fail %s", err)
return nil
}
guestRows := manager.SGuestResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, guestList, fields, isList)
gns, err := GuestnetworkManager.fetchGuestnetworksByGuestnetworkIndex(guestIds, guestNetworkIdx)
if err != nil {
log.Errorf("failed fetchGuestnetworksByGuestnetworkIndex")
return nil
}
regionList := make([]interface{}, len(objs))
managerList := make([]interface{}, len(objs))
vpcList := make([]interface{}, len(objs))
projectList := make([]interface{}, len(objs))
for i := range rows {
secgroupId := objs[i].(*SGuestnetworksecgroup).SecgroupId
guestId := objs[i].(*SGuestnetworksecgroup).GuestId
networkIndex := objs[i].(*SGuestnetworksecgroup).NetworkIndex
rows[i].GuestResourceInfo = guestRows[i]
rows[i].NetworkIndex = networkIndex
rows[i].Admin = objs[i].(*SGuestnetworksecgroup).Admin
rows[i].GuestNetwork = path.Join(guestId, secgroupId, strconv.Itoa(rows[i].NetworkIndex))
if group, ok := groups[secgrpIds[i]]; ok {
rows[i].Secgroup = group.Name
rows[i].CloudregionId = group.CloudregionId
rows[i].ManagerId = group.ManagerId
rows[i].VpcId = group.VpcId
rows[i].SecgroupStatus = group.Status
rows[i].ProjectId = group.ProjectId
secgroup := group
projectList[i] = &secgroup
}
regionList[i] = &SCloudregionResourceBase{rows[i].CloudregionId}
managerList[i] = &SManagedResourceBase{rows[i].ManagerId}
vpcList[i] = &SVpcResourceBase{rows[i].VpcId}
key := fmt.Sprintf("%s/%d", guestId, networkIndex)
if gn, ok := gns[key]; ok {
rows[i].MacAddr = gn.MacAddr
rows[i].IpAddr = gn.IpAddr
rows[i].Ip6Addr = gn.Ip6Addr
rows[i].Ifname = gn.Ifname
}
}
projRows := SecurityGroupManager.SProjectizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, projectList, fields, isList)
regionRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, regionList, fields, isList)
managerRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, managerList, fields, isList)
vpcRows := manager.SVpcResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, vpcList, fields, isList)
for i := range rows {
rows[i].ProjectizedResourceInfo = projRows[i]
rows[i].CloudregionResourceInfo = regionRows[i]
rows[i].ManagedResourceInfo = managerRows[i]
rows[i].Vpc = vpcRows[i].Vpc
}
return rows
}
func (manager *SGuestnetworkManager) fetchGuestnetworksByGuestnetworkIndex(guestIds []string, networkIndex []int) (map[string]SGuestnetwork, error) {
q := manager.Query()
q = q.In("guest_id", guestIds)
q = q.In("index", networkIndex)
gns := make([]SGuestnetwork, 0)
err := q.All(&gns)
if err != nil {
return nil, err
}
res := map[string]SGuestnetwork{}
for i := range gns {
key := fmt.Sprintf("%s/%d", gns[i].GuestId, gns[i].Index)
if _, ok := res[key]; !ok {
res[key] = gns[i]
}
}
return res, nil
}
func (manager *SGuestnetworksecgroupManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
q, err := manager.SResourceBaseManager.QueryDistinctExtraField(q, field)
if err == nil {
return q, nil
}
q, err = manager.SGuestResourceBaseManager.QueryDistinctExtraField(q, field)
if err == nil {
return q, nil
}
q, err = manager.SSecurityGroupResourceBaseManager.QueryDistinctExtraField(q, field)
if err == nil {
return q, nil
}
return q, httperrors.ErrNotFound
}
func (manager *SGuestnetworksecgroupManager) QueryDistinctExtraFields(q *sqlchemy.SQuery, resource string, fields []string) (*sqlchemy.SQuery, error) {
q, err := manager.SResourceBaseManager.QueryDistinctExtraFields(q, resource, fields)
if err == nil {
return q, nil
}
q, err = manager.SGuestResourceBaseManager.QueryDistinctExtraFields(q, resource, fields)
if err == nil {
return q, nil
}
q, err = manager.SSecurityGroupResourceBaseManager.QueryDistinctExtraFields(q, resource, fields)
if err == nil {
return q, nil
}
return q, httperrors.ErrNotFound
}
func (manager *SGuestnetworksecgroupManager) GetGuestnetworksecgroups(guestId string, networkIndex int) ([]SSecurityGroup, error) {
q := GuestnetworksecgroupManager.Query("secgroup_id").Equals("guest_id", guestId)
if networkIndex >= 0 {
q = q.Equals("network_index", networkIndex)
}
subQ := q.SubQuery()
secgrpQuery := SecurityGroupManager.Query()
secgrpQuery = secgrpQuery.In("id", subQ)
secgroups := []SSecurityGroup{}
err := db.FetchModelObjects(SecurityGroupManager, secgrpQuery, &secgroups)
if err != nil {
return nil, errors.Wrapf(err, "db.FetchModelObjects")
}
return secgroups, nil
}
// guest network attach secgroup
func (self *SGuest) PerformAddNetworkSecgroup(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
input api.GuestNetworkAddSecgroupInput,
) (jsonutils.JSONObject, error) {
if !utils.IsInStringArray(self.Status, []string{api.VM_READY, api.VM_RUNNING, api.VM_SUSPEND}) {
return nil, httperrors.NewInputParameterError("Cannot add security groups in status %s", self.Status)
}
if input.NetworkIndex == nil || *input.NetworkIndex < 0 {
return nil, httperrors.NewBadRequestError("input network index %#v is invalid", input.NetworkIndex)
}
driver, _ := self.GetDriver()
maxCount := driver.GetMaxSecurityGroupCount()
if maxCount == 0 {
return nil, httperrors.NewUnsupportOperationError("Cannot add security groups for hypervisor %s", self.Hypervisor)
}
if len(input.SecgroupIds) == 0 {
return nil, httperrors.NewMissingParameterError("secgroup_ids")
}
guestnetwork, err := self.getGuestnetworkByIndex(*input.NetworkIndex)
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrap(err, "getGuestnetworkByIndex"))
}
secgroups, err := GuestnetworksecgroupManager.GetGuestnetworksecgroups(self.Id, *input.NetworkIndex)
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrap(err, "GetGuestnetworksecgroups"))
}
if len(secgroups)+len(input.SecgroupIds) > maxCount {
return nil, httperrors.NewUnsupportOperationError("guest %s band to up to %d security groups", self.Name, maxCount)
}
network, err := guestnetwork.GetNetwork()
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrap(err, "GetNetwork"))
}
vpc, err := network.GetVpc()
if err != nil {
return nil, errors.Wrap(err, "GetVpc")
}
secgroupIds := []string{}
for _, secgroup := range secgroups {
secgroupIds = append(secgroupIds, secgroup.Id)
}
secgroupNames := []string{}
for i := range input.SecgroupIds {
secObj, err := validators.ValidateModel(ctx, userCred, SecurityGroupManager, &input.SecgroupIds[i])
if err != nil {
return nil, err
}
secgroup := secObj.(*SSecurityGroup)
if utils.IsInStringArray(secObj.GetId(), secgroupIds) {
return nil, httperrors.NewInputParameterError(
"security group %s has already been assigned to guest %s network %d",
secObj.GetName(), self.GetName(), input.NetworkIndex)
}
err = vpc.CheckSecurityGroupConsistent(secgroup)
if err != nil {
return nil, err
}
secgroupIds = append(secgroupIds, secgroup.GetId())
secgroupNames = append(secgroupNames, secgroup.Name)
}
err = self.SaveNetworkSecgroups(ctx, userCred, secgroupIds, *input.NetworkIndex)
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrap(err, "SaveNetworkSecgroups"))
}
notes := map[string][]string{"secgroups": secgroupNames}
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_VM_ASSIGNSECGROUP, notes, userCred, true)
return nil, self.StartSyncTask(ctx, userCred, true, "")
}
func (self *SGuest) PerformRevokeNetworkSecgroup(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
input api.GuestRevokeNetworkSecgroupInput,
) (jsonutils.JSONObject, error) {
if !utils.IsInStringArray(self.Status, []string{api.VM_READY, api.VM_RUNNING, api.VM_SUSPEND}) {
return nil, httperrors.NewInputParameterError("Cannot revoke security groups in status %s", self.Status)
}
if len(input.SecgroupIds) == 0 {
return nil, nil
}
var guestnetwork *SGuestnetwork
var err error
if input.MacAddr != "" {
guestnetwork, err = self.GetGuestnetworkByMac(input.MacAddr)
} else if input.NetworkIndex != nil {
guestnetwork, err = self.getGuestnetworkByIndex(*input.NetworkIndex)
} else {
return nil, httperrors.NewBadRequestError("no valid network index or mac addr")
}
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrap(err, "get guest network"))
}
secgroups, err := GuestnetworksecgroupManager.GetGuestnetworksecgroups(self.Id, guestnetwork.Index)
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrap(err, "GetGuestnetworksecgroups"))
}
secgroupMaps := map[string]string{}
for _, secgroup := range secgroups {
secgroupMaps[secgroup.Id] = secgroup.Name
}
secgroupNames := []string{}
for i := range input.SecgroupIds {
secObj, err := validators.ValidateModel(ctx, userCred, SecurityGroupManager, &input.SecgroupIds[i])
if err != nil {
return nil, err
}
secgrp := secObj.(*SSecurityGroup)
_, ok := secgroupMaps[secgrp.GetId()]
if !ok {
return nil, httperrors.NewInputParameterError("security group %s network index %d not assigned to guest %s",
secgrp.GetName(), guestnetwork.Index, self.GetName())
}
delete(secgroupMaps, secgrp.GetId())
secgroupNames = append(secgroupNames, secgrp.GetName())
}
secgrpIds := []string{}
for secgroupId := range secgroupMaps {
secgrpIds = append(secgrpIds, secgroupId)
}
err = self.SaveNetworkSecgroups(ctx, userCred, secgrpIds, guestnetwork.Index)
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrap(err, "SaveNetworkSecgroups"))
}
notes := map[string][]string{"secgroups": secgroupNames}
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_VM_REVOKESECGROUP, notes, userCred, true)
return nil, self.StartSyncTask(ctx, userCred, true, "")
}
func (self *SGuest) PerformSetNetworkSecgroup(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
input api.GuestSetNetworkSecgroupInput,
) (jsonutils.JSONObject, error) {
if !utils.IsInStringArray(self.Status, []string{api.VM_READY, api.VM_RUNNING, api.VM_SUSPEND}) {
return nil, httperrors.NewInputParameterError("Cannot set security rules in status %s", self.Status)
}
if len(input.SecgroupIds) == 0 {
return nil, httperrors.NewMissingParameterError("secgroup_ids")
}
driver, _ := self.GetDriver()
maxCount := driver.GetMaxSecurityGroupCount()
if maxCount == 0 {
return nil, httperrors.NewUnsupportOperationError("Cannot set security group for this guest %s", self.Name)
}
if len(input.SecgroupIds) > maxCount {
return nil, httperrors.NewUnsupportOperationError("guest %s band to up to %d security groups", self.Name, maxCount)
}
var guestnetwork *SGuestnetwork
var err error
if input.MacAddr != "" {
guestnetwork, err = self.GetGuestnetworkByMac(input.MacAddr)
} else if input.NetworkIndex != nil {
guestnetwork, err = self.getGuestnetworkByIndex(*input.NetworkIndex)
} else {
return nil, httperrors.NewBadRequestError("no valid network index or mac addr")
}
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrap(err, "get guest network"))
}
network, err := guestnetwork.GetNetwork()
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrap(err, "GetNetwork"))
}
vpc, err := network.GetVpc()
if err != nil {
return nil, errors.Wrap(err, "GetVpc")
}
secgroupIds := []string{}
secgroupNames := []string{}
for i := range input.SecgroupIds {
secObj, err := validators.ValidateModel(ctx, userCred, SecurityGroupManager, &input.SecgroupIds[i])
if err != nil {
return nil, err
}
secgrp := secObj.(*SSecurityGroup)
err = vpc.CheckSecurityGroupConsistent(secgrp)
if err != nil {
return nil, err
}
if !utils.IsInStringArray(secgrp.GetId(), secgroupIds) {
secgroupIds = append(secgroupIds, secgrp.GetId())
secgroupNames = append(secgroupNames, secgrp.GetName())
}
}
err = self.SaveNetworkSecgroups(ctx, userCred, secgroupIds, guestnetwork.Index)
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "SaveNetworkSecgroups"))
}
notes := map[string][]string{"secgroups": secgroupNames}
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_VM_SETSECGROUP, notes, userCred, true)
return nil, self.StartSyncTask(ctx, userCred, true, "")
}
func (self *SGuest) SaveNetworkSecgroups(
ctx context.Context, userCred mcclient.TokenCredential, secgroupIds []string, networkIndex int,
) error {
if len(secgroupIds) == 0 {
return self.RevokeNetworkAllSecgroups(ctx, userCred, networkIndex)
}
oldIds := set.New(set.ThreadSafe)
newIds := set.New(set.ThreadSafe)
gnss, err := self.GetGuestNetworkSecgroups(networkIndex)
if err != nil {
return errors.Wrap(err, "GetGuestNetworkSecgroups")
}
secgroupMaps := map[string]SGuestnetworksecgroup{}
for i := range gnss {
oldIds.Add(gnss[i].SecgroupId)
secgroupMaps[gnss[i].SecgroupId] = gnss[i]
}
for i := range secgroupIds {
newIds.Add(secgroupIds[i])
}
for _, removed := range set.Difference(oldIds, newIds).List() {
id := removed.(string)
gns, ok := secgroupMaps[id]
if ok {
err = gns.Delete(ctx, userCred)
if err != nil {
return errors.Wrapf(err,
"Delete guest network secgroup for guest %s network index %d secgroup %s",
self.GetName(), networkIndex, id)
}
}
}
for _, added := range set.Difference(newIds, oldIds).List() {
id := added.(string)
err = self.newGuestNetworkSecgroup(ctx, id, networkIndex, false)
if err != nil {
return errors.Wrapf(err,
"New guest network secgroup for guest %s network index %d with secgroup %s",
self.GetName(), networkIndex, id)
}
}
return nil
}
func (self *SGuest) newGuestNetworkSecgroup(ctx context.Context, secgroupId string, networkIndex int, isAdmin bool) error {
gns := &SGuestnetworksecgroup{}
gns.SetModelManager(GuestnetworksecgroupManager, gns)
gns.GuestId = self.Id
gns.SecgroupId = secgroupId
gns.NetworkIndex = networkIndex
gns.Admin = isAdmin
return GuestnetworksecgroupManager.TableSpec().Insert(ctx, gns)
}
func (self *SGuest) GetGuestNetworkSecgroups(networkIndex int) ([]SGuestnetworksecgroup, error) {
gss := []SGuestnetworksecgroup{}
q := GuestnetworksecgroupManager.Query().Equals("guest_id", self.Id).Equals("network_index", networkIndex)
err := db.FetchModelObjects(GuestnetworksecgroupManager, q, &gss)
if err != nil {
return nil, errors.Wrapf(err, "db.FetchModelObjects")
}
return gss, nil
}
func (self *SGuest) RevokeNetworkAllSecgroups(ctx context.Context, userCred mcclient.TokenCredential, networkIndex int) error {
gss, err := self.GetGuestNetworkSecgroups(networkIndex)
if err != nil {
return errors.Wrapf(err, "GetGuestNetworkSecgroups")
}
for i := range gss {
err = gss[i].Delete(ctx, userCred)
if err != nil {
return errors.Wrap(err, "Delete")
}
}
//return self.newGuestNetworkSecgroup(ctx, options.Options.DefaultSecurityGroupId, networkIndex, false)
return nil
}
func (self *SGuestnetworksecgroupManager) getNetworkSecgroupJson(guestId string, networkIndex int) ([]*api.SecgroupJsonDesc, error) {
ret := []*api.SecgroupJsonDesc{}
secgroups, err := GuestnetworksecgroupManager.GetGuestnetworksecgroups(guestId, networkIndex)
if err != nil {
return nil, errors.Wrap(err, "GetSecgroups")
}
for _, secGrp := range secgroups {
ret = append(ret, secGrp.getDesc())
}
return ret, nil
}
func (self *SGuest) RevokeAllNetworkSecgroups(ctx context.Context, userCred mcclient.TokenCredential) error {
gns, err := self.GetNetworks("")
if err != nil {
return errors.Wrap(err, "GetNetworks")
}
for i := range gns {
gnss, err := self.GetGuestNetworkSecgroups(gns[i].Index)
if err != nil {
return errors.Wrap(err, "GetGuestNetworkSecgroups")
}
for j := range gnss {
err = gnss[j].Delete(ctx, userCred)
if err != nil {
return errors.Wrap(err, "Delete guestnetworksecgroup")
}
}
}
return nil
}
+2 -2
View File
@@ -32,7 +32,7 @@ import (
)
type SGuestResourceBase struct {
GuestId string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"`
GuestId string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional" json:"guest_id"`
}
type SGuestResourceBaseManager struct {
@@ -98,7 +98,7 @@ func (manager *SGuestResourceBaseManager) FetchCustomizeColumns(
var base *SGuestResourceBase
err := reflectutils.FindAnonymouStructPointer(objs[i], &base)
if err != nil {
log.Errorf("Cannot find SGuestResourceBase in object %s", objs[i])
log.Errorf("Cannot find SGuestResourceBase in object %s %s", objs[i], err)
continue
}
guestIds[i] = base.GuestId
+53 -10
View File
@@ -1225,6 +1225,18 @@ func (guest *SGuest) ConvertEsxiNetworks(targetGuest *SGuest) error {
return err
}
func (guest *SGuest) getGuestnetworkByIndex(networkIndex int) (*SGuestnetwork, error) {
q := guest.GetNetworksQuery("").Equals("index", networkIndex)
guestnic := SGuestnetwork{}
err := q.First(&guestnic)
if err != nil {
return nil, err
}
guestnic.SetModelManager(GuestnetworkManager, &guestnic)
return &guestnic, nil
}
func (guest *SGuest) getGuestnetworkByIpOrMac(ipAddr string, ip6Addr string, macAddr string) (*SGuestnetwork, error) {
q := guest.GetNetworksQuery("")
if len(ipAddr) > 0 {
@@ -2142,6 +2154,11 @@ func (manager *SGuestManager) validateCreateData(
netConfig.SriovDevice = devConfig
netConfig.Driver = api.NETWORK_DRIVER_VFIO
}
secgroupIds, err := isValidSecgroups(ctx, userCred, netConfig.Secgroups)
if err != nil {
return nil, err
}
netConfig.Secgroups = secgroupIds
netConfig.Project = ownerId.GetProjectId()
netConfig.Domain = ownerId.GetProjectDomainId()
@@ -2208,15 +2225,9 @@ func (manager *SGuestManager) validateCreateData(
input.KeypairId = keypairObj.GetId()
}
secGrpIds := []string{}
for _, secgroup := range input.Secgroups {
secGrpObj, err := SecurityGroupManager.FetchByIdOrName(ctx, userCred, secgroup)
if err != nil {
return nil, httperrors.NewResourceNotFoundError("Secgroup %s not found", secgroup)
}
if !utils.IsInStringArray(secGrpObj.GetId(), secGrpIds) {
secGrpIds = append(secGrpIds, secGrpObj.GetId())
}
secGrpIds, err := isValidSecgroups(ctx, userCred, input.Secgroups)
if err != nil {
return nil, err
}
if len(secGrpIds) > 0 {
input.SecgroupId = secGrpIds[0]
@@ -3348,6 +3359,26 @@ func (self *SGuest) getSecurityGroupsRules() string {
return strings.Join(rules, SECURITY_GROUP_SEPARATOR)
}
func (self *SGuest) getNetworkSecurityGroupsRules(networkIndex int) string {
gnss, _ := self.GetGuestNetworkSecgroups(networkIndex)
secgroupids := []string{}
for _, gns := range gnss {
secgroupids = append(secgroupids, gns.SecgroupId)
}
q := SecurityGroupRuleManager.Query()
q.Filter(sqlchemy.In(q.Field("secgroup_id"), secgroupids)).Desc(q.Field("priority"), q.Field("action"))
secrules := []SSecurityGroupRule{}
if err := db.FetchModelObjects(SecurityGroupRuleManager, q, &secrules); err != nil {
log.Errorf("Get security group rules error: %v", err)
return ""
}
rules := []string{}
for _, rule := range secrules {
rules = append(rules, rule.String())
}
return strings.Join(rules, SECURITY_GROUP_SEPARATOR)
}
func (self *SGuest) getAdminSecurityRules() string {
secgrp := self.getAdminSecgroup()
if secgrp != nil {
@@ -4674,7 +4705,12 @@ func (self *SGuest) CreateNetworksOnHost(
return errors.Wrap(err, "self.allocSriovNicDevice")
}
}
if len(netConfig.Secgroups) > 0 {
err = self.SaveNetworkSecgroups(ctx, userCred, netConfig.Secgroups, gns[0].Index)
if err != nil {
return errors.Wrap(err, "SaveNetworkSecgroups")
}
}
}
return nil
}
@@ -5630,6 +5666,13 @@ func (self *SGuest) GetJsonDescAtHypervisor(ctx context.Context, host *SHost) *a
if len(nicDesc.Domain) > 0 {
desc.Domain = nicDesc.Domain
}
secgroupDesc := nic.getSecgroupDesc()
if secgroupDesc != nil {
if desc.NicSecgroups == nil {
desc.NicSecgroups = make([]*api.GuestnetworkSecgroupDesc, 0)
}
desc.NicSecgroups = append(desc.NicSecgroups, secgroupDesc)
}
}
{
+1
View File
@@ -104,6 +104,7 @@ func (manager *SSecurityGroupResourceBaseManager) FetchCustomizeColumns(
regionRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, regionList, fields, isList)
managerRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, managerList, fields, isList)
for i := range rows {
rows[i].CloudregionResourceInfo = regionRows[i]
rows[i].ManagedResourceInfo = managerRows[i]
+21
View File
@@ -410,6 +410,7 @@ func (manager *SSecurityGroupManager) FetchCustomizeColumns(
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 {
@@ -456,6 +457,22 @@ func (manager *SSecurityGroupManager) FetchCustomizeColumns(
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
@@ -464,6 +481,7 @@ func (manager *SSecurityGroupManager) FetchCustomizeColumns(
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
@@ -1003,6 +1021,7 @@ func (sm *SSecurityGroupManager) TotalCnt(secIds []string) (map[string]api.SSecu
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)
@@ -1016,6 +1035,7 @@ func (sm *SSecurityGroupManager) TotalCnt(secIds []string) (map[string]api.SSecu
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"))
@@ -1026,6 +1046,7 @@ func (sm *SSecurityGroupManager) TotalCnt(secIds []string) (map[string]api.SSecu
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"))
+1
View File
@@ -170,6 +170,7 @@ func InitHandlers(app *appsrv.Application, isSlave bool) {
models.InterVpcNetworkRouteSetManager,
models.GuestScreenDumpManager,
models.BillingResourceCheckManager,
models.GuestnetworksecgroupManager,
models.SchedpolicyManager,
models.DynamicschedtagManager,
@@ -340,6 +340,7 @@ func (deleteTask *BaseGuestDeleteTask) OnGuestDeleteCompleteFailed(ctx context.C
func (deleteTask *BaseGuestDeleteTask) OnGuestDeleteComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
guest := obj.(*models.SGuest)
guest.RevokeAllNetworkSecgroups(ctx, deleteTask.UserCred)
guest.DetachAllNetworks(ctx, deleteTask.UserCred)
guest.EjectAllIso(deleteTask.UserCred)
guest.EjectAllVfd(deleteTask.UserCred)
+5 -3
View File
@@ -379,11 +379,13 @@ type SGuestControlDesc struct {
// is volatile host meaning guest not running on this host right now
IsVolatileHost bool
ScalingGroupId string
ScalingGroupId string
SrcIpCheck bool
SrcMacCheck bool
SecurityRules string
AdminSecurityRules string
SrcIpCheck bool
SrcMacCheck bool
NicSecgroups []*api.GuestnetworkSecgroupDesc `json:"nic_secgroups,omitempty"`
EncryptKeyId string
@@ -0,0 +1,33 @@
// 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/onecloud/pkg/mcclient/modulebase"
"yunion.io/x/onecloud/pkg/mcclient/modules"
)
var (
Servernetworksecgroups modulebase.ResourceManager
)
func init() {
Servernetworksecgroups = modules.NewComputeManager(
"guestnetworksecgroup",
"guestnetworksecgroups",
[]string{"Guest_id", "Network_index", "Secgroup_id", "Admin"},
[]string{})
modules.RegisterCompute(&Servernetworksecgroups)
}
+13
View File
@@ -197,3 +197,16 @@ type SecgroupCleanOptions struct {
func (opts *SecgroupCleanOptions) Params() (jsonutils.JSONObject, error) {
return nil, nil
}
type ServerNetworkSecgroupListOptions struct {
baseoptions.BaseListOptions
Server string `help:"Server Id or name"`
Secgroup string `help:"Secgroup Id or name"`
NetworkIndex *int `help:"Server network index"`
IsAdmin bool `help:"Is admin secgroup"`
}
func (opts *ServerNetworkSecgroupListOptions) Params() (jsonutils.JSONObject, error) {
return baseoptions.ListStructToParams(opts)
}
+14
View File
@@ -894,6 +894,20 @@ func (opts *ServerSecGroupsOptions) Params() (jsonutils.JSONObject, error) {
return jsonutils.Marshal(map[string][]string{"secgroup_ids": opts.SecgroupIds}), nil
}
type ServerNetworkSecGroupsOptions struct {
ID string `help:"ID or Name of server" metavar:"Guest" json:"-"`
NetworkIndex *int `help:"Guest network index" metavar:"Network Index"`
SecgroupIds []string `help:"Ids of Security Groups" metavar:"Security Groups" positional:"true"`
}
func (o *ServerNetworkSecGroupsOptions) GetId() string {
return o.ID
}
func (opts *ServerNetworkSecGroupsOptions) Params() (jsonutils.JSONObject, error) {
return jsonutils.Marshal(opts), nil
}
type ServerModifySrcCheckOptions struct {
ID string `help:"ID or Name of server" metavar:"Guest" json:"-"`
SrcIpCheck string `help:"Turn on/off src ip check" choices:"on|off"`
+19
View File
@@ -88,6 +88,9 @@ type Guestnetwork struct {
Network *Network `json:"-"`
Elasticip *Elasticip `json:"-"`
SubIPs NetworkAddresses `json:"-"`
// guest nic level secgroup
Guestnetworksecgroups Guestnetworksecgroups `json:"-"`
}
func (el *Guestnetwork) Copy() *Guestnetwork {
@@ -109,6 +112,22 @@ func (el *NetworkAddress) Copy() *NetworkAddress {
}
}
type Guestnetworksecgroup struct {
compute_models.SGuestnetworksecgroup
SecurityGroup *SecurityGroup `json:"-"`
}
func (el *Guestnetworksecgroup) ModelSetKey() string {
return fmt.Sprintf("%s/%d", el.GuestId, el.NetworkIndex)
}
func (el *Guestnetworksecgroup) Copy() *Guestnetworksecgroup {
return &Guestnetworksecgroup{
SGuestnetworksecgroup: el.SGuestnetworksecgroup,
}
}
type Guest struct {
compute_models.SGuest
+56 -2
View File
@@ -39,8 +39,9 @@ type (
Elasticips map[string]*Elasticip
NetworkAddresses map[string]*NetworkAddress
Guestnetworks map[string]*Guestnetwork // key: rowId
Guestsecgroups map[string]*Guestsecgroup // key: guestId/secgroupId
Guestnetworks map[string]*Guestnetwork // key: rowId
Guestsecgroups map[string]*Guestsecgroup // key: guestId/secgroupId
Guestnetworksecgroups map[string]*Guestnetworksecgroup // key: guestId/networkIndex
DnsZones map[string]*DnsZone
DnsRecords map[string]*DnsRecord
@@ -583,6 +584,59 @@ func (set Guestnetworks) joinNetworkAddresses(subEntries NetworkAddresses) bool
return correct
}
func (set Guestnetworks) joinGuestnetworksecgroups(subEntries Guestnetworksecgroups) bool {
for _, gn := range set {
key := fmt.Sprintf("%s/%d", gn.GuestId, gn.Index)
gns, ok := subEntries[key]
if !ok {
continue
}
if len(gn.Guestnetworksecgroups) == 0 {
gn.Guestnetworksecgroups = Guestnetworksecgroups{}
}
gn.Guestnetworksecgroups[key] = gns
}
return true
}
func (set Guestnetworksecgroups) ModelManager() mcclient_modulebase.IBaseManager {
return &mcclient_modules.Servernetworksecgroups
}
func (set Guestnetworksecgroups) DBModelManager() db.IModelManager {
return models.GuestnetworksecgroupManager
}
func (set Guestnetworksecgroups) NewModel() db.IModel {
return &Guestnetworksecgroup{}
}
func (set Guestnetworksecgroups) AddModel(i db.IModel) {
m := i.(*Guestnetworksecgroup)
k := m.ModelSetKey()
set[k] = m
}
func (set Guestnetworksecgroups) Copy() apihelper.IModelSet {
setCopy := Guestnetworksecgroups{}
for id, el := range set {
setCopy[id] = el.Copy()
}
return setCopy
}
func (set Guestnetworksecgroups) joinSecurityGroups(subEntries SecurityGroups) bool {
for _, gns := range set {
key := gns.SecgroupId
secgroup, ok := subEntries[key]
if !ok {
continue
}
gns.SecurityGroup = secgroup
}
return true
}
func (set NetworkAddresses) ModelManager() mcclient_modulebase.IBaseManager {
return &mcclient_modules.NetworkAddresses
}
+65 -55
View File
@@ -27,17 +27,18 @@ import (
)
type ModelSetsMaxUpdatedAt struct {
Vpcs time.Time
Wires time.Time
Networks time.Time
Guests time.Time
Hosts time.Time
SecurityGroups time.Time
SecurityGroupRules time.Time
Guestnetworks time.Time
Guestsecgroups time.Time
Elasticips time.Time
NetworkAddresses time.Time
Vpcs time.Time
Wires time.Time
Networks time.Time
Guests time.Time
Hosts time.Time
SecurityGroups time.Time
SecurityGroupRules time.Time
Guestnetworks time.Time
Guestsecgroups time.Time
Elasticips time.Time
NetworkAddresses time.Time
Guestnetworksecgroups time.Time
DnsZones time.Time
DnsRecords time.Time
@@ -54,17 +55,18 @@ type ModelSetsMaxUpdatedAt struct {
func NewModelSetsMaxUpdatedAt() *ModelSetsMaxUpdatedAt {
return &ModelSetsMaxUpdatedAt{
Vpcs: apihelper.PseudoZeroTime,
Wires: apihelper.PseudoZeroTime,
Networks: apihelper.PseudoZeroTime,
Guests: apihelper.PseudoZeroTime,
Hosts: apihelper.PseudoZeroTime,
SecurityGroups: apihelper.PseudoZeroTime,
SecurityGroupRules: apihelper.PseudoZeroTime,
Guestnetworks: apihelper.PseudoZeroTime,
Guestsecgroups: apihelper.PseudoZeroTime,
Elasticips: apihelper.PseudoZeroTime,
NetworkAddresses: apihelper.PseudoZeroTime,
Vpcs: apihelper.PseudoZeroTime,
Wires: apihelper.PseudoZeroTime,
Networks: apihelper.PseudoZeroTime,
Guests: apihelper.PseudoZeroTime,
Hosts: apihelper.PseudoZeroTime,
SecurityGroups: apihelper.PseudoZeroTime,
SecurityGroupRules: apihelper.PseudoZeroTime,
Guestnetworks: apihelper.PseudoZeroTime,
Guestsecgroups: apihelper.PseudoZeroTime,
Elasticips: apihelper.PseudoZeroTime,
NetworkAddresses: apihelper.PseudoZeroTime,
Guestnetworksecgroups: apihelper.PseudoZeroTime,
DnsZones: apihelper.PseudoZeroTime,
DnsRecords: apihelper.PseudoZeroTime,
@@ -81,17 +83,18 @@ func NewModelSetsMaxUpdatedAt() *ModelSetsMaxUpdatedAt {
}
type ModelSets struct {
Vpcs Vpcs
Wires Wires
Networks Networks
Guests Guests
Hosts Hosts
SecurityGroups SecurityGroups
SecurityGroupRules SecurityGroupRules
Guestnetworks Guestnetworks
Guestsecgroups Guestsecgroups
Elasticips Elasticips
NetworkAddresses NetworkAddresses
Vpcs Vpcs
Wires Wires
Networks Networks
Guests Guests
Hosts Hosts
SecurityGroups SecurityGroups
SecurityGroupRules SecurityGroupRules
Guestnetworks Guestnetworks
Guestsecgroups Guestsecgroups
Elasticips Elasticips
NetworkAddresses NetworkAddresses
Guestnetworksecgroups Guestnetworksecgroups
DnsZones DnsZones
DnsRecords DnsRecords
@@ -109,17 +112,18 @@ type ModelSets struct {
func NewModelSets() *ModelSets {
return &ModelSets{
Vpcs: Vpcs{},
Wires: Wires{},
Networks: Networks{},
Guests: Guests{},
Hosts: Hosts{},
SecurityGroups: SecurityGroups{},
SecurityGroupRules: SecurityGroupRules{},
Guestnetworks: Guestnetworks{},
Guestsecgroups: Guestsecgroups{},
Elasticips: Elasticips{},
NetworkAddresses: NetworkAddresses{},
Vpcs: Vpcs{},
Wires: Wires{},
Networks: Networks{},
Guests: Guests{},
Hosts: Hosts{},
SecurityGroups: SecurityGroups{},
SecurityGroupRules: SecurityGroupRules{},
Guestnetworks: Guestnetworks{},
Guestsecgroups: Guestsecgroups{},
Elasticips: Elasticips{},
NetworkAddresses: NetworkAddresses{},
Guestnetworksecgroups: Guestnetworksecgroups{},
DnsZones: DnsZones{},
DnsRecords: DnsRecords{},
@@ -150,6 +154,7 @@ func (mss *ModelSets) ModelSetList() []apihelper.IModelSet {
mss.Guestsecgroups,
mss.Elasticips,
mss.NetworkAddresses,
mss.Guestnetworksecgroups,
mss.DnsZones,
mss.DnsRecords,
@@ -172,17 +177,18 @@ func (mss *ModelSets) NewEmpty() apihelper.IModelSets {
func (mss *ModelSets) copy_() *ModelSets {
mssCopy := &ModelSets{
Vpcs: mss.Vpcs.Copy().(Vpcs),
Wires: mss.Wires.Copy().(Wires),
Networks: mss.Networks.Copy().(Networks),
Guests: mss.Guests.Copy().(Guests),
Hosts: mss.Hosts.Copy().(Hosts),
SecurityGroups: mss.SecurityGroups.Copy().(SecurityGroups),
SecurityGroupRules: mss.SecurityGroupRules.Copy().(SecurityGroupRules),
Guestnetworks: mss.Guestnetworks.Copy().(Guestnetworks),
Guestsecgroups: mss.Guestsecgroups.Copy().(Guestsecgroups),
Elasticips: mss.Elasticips.Copy().(Elasticips),
NetworkAddresses: mss.NetworkAddresses.Copy().(NetworkAddresses),
Vpcs: mss.Vpcs.Copy().(Vpcs),
Wires: mss.Wires.Copy().(Wires),
Networks: mss.Networks.Copy().(Networks),
Guests: mss.Guests.Copy().(Guests),
Hosts: mss.Hosts.Copy().(Hosts),
SecurityGroups: mss.SecurityGroups.Copy().(SecurityGroups),
SecurityGroupRules: mss.SecurityGroupRules.Copy().(SecurityGroupRules),
Guestnetworks: mss.Guestnetworks.Copy().(Guestnetworks),
Guestsecgroups: mss.Guestsecgroups.Copy().(Guestsecgroups),
Elasticips: mss.Elasticips.Copy().(Elasticips),
NetworkAddresses: mss.NetworkAddresses.Copy().(NetworkAddresses),
Guestnetworksecgroups: mss.Guestnetworksecgroups.Copy().(Guestnetworksecgroups),
DnsZones: mss.DnsZones.Copy().(DnsZones),
DnsRecords: mss.DnsRecords.Copy().(DnsRecords),
@@ -273,12 +279,16 @@ func (mss *ModelSets) join() bool {
msg = append(msg, "mss.SecurityGroups.joinSecurityGroupRules(mss.SecurityGroupRules)")
p = append(p, mss.Guestsecgroups.join(mss.SecurityGroups, mss.Guests))
msg = append(msg, "mss.Guestsecgroups.join(mss.SecurityGroups, mss.Guests)")
p = append(p, mss.Guestnetworksecgroups.joinSecurityGroups(mss.SecurityGroups))
msg = append(msg, "mss.Guestnetworksecgroups.joinSecurityGroups(mss.SecurityGroups)")
p = append(p, mss.Guestnetworks.joinGuests(mss.Guests))
msg = append(msg, "mss.Guestnetworks.joinGuests(mss.Guests)")
p = append(p, mss.Guestnetworks.joinElasticips(mss.Elasticips))
msg = append(msg, "mss.Guestnetworks.joinElasticips(mss.Elasticips)")
p = append(p, mss.Guestnetworks.joinNetworkAddresses(mss.NetworkAddresses))
msg = append(msg, "mss.Guestnetworks.joinNetworkAddresses(mss.NetworkAddresses)")
p = append(p, mss.Guestnetworks.joinGuestnetworksecgroups(mss.Guestnetworksecgroups))
msg = append(msg, "mss.Guestnetworks.joinGuestnetworksecgroups(mss.Guestnetworksecgroups)")
p = append(p, mss.Groups.joinGroupnetworks(mss.Groupnetworks, mss.Networks))
msg = append(msg, "mss.Groups.joinGroupnetworks(mss.Groupnetworks, mss.Networks)")
p = append(p, mss.Groupnetworks.joinElasticips(mss.Elasticips))
+31
View File
@@ -53,6 +53,37 @@ func (el *Guest) OrderedSecurityGroupRules() []*SecurityGroupRule {
return rs
}
func (el *Guestnetwork) OrderedSecurityGroupRules(guest *Guest) []*SecurityGroupRule {
if len(el.Guestnetworksecgroups) == 0 {
return guest.OrderedSecurityGroupRules()
}
// deny any incoming traffic and allow ARP
rs := []*SecurityGroupRule{
{
// deny all in-bound traffic
SSecurityGroupRule: compute_models.SSecurityGroupRule{
Priority: 1,
Direction: string(secrules.SecurityRuleIngress),
Action: string(secrules.SecurityRuleDeny),
},
},
{
// allow in-bound arp traffic
SSecurityGroupRule: compute_models.SSecurityGroupRule{
Priority: 2,
Direction: string(secrules.SecurityRuleIngress),
Protocol: "arp",
Action: string(secrules.SecurityRuleAllow),
},
},
}
for _, guestSecgroup := range el.Guestnetworksecgroups {
rs = append(rs, guestSecgroup.SecurityGroup.securityGroupRules(100)...)
}
sort.Slice(rs, SecurityGroupRuleLessFunc(rs))
return rs
}
func (el *SecurityGroup) securityGroupRules(basePriority int64) []*SecurityGroupRule {
rs := make([]*SecurityGroupRule, 0, len(el.SecurityGroupRules))
for _, r := range el.SecurityGroupRules {
+1 -1
View File
@@ -822,7 +822,7 @@ func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestn
if len(guestnetwork.Ip6Addr) > 0 {
enableIPv6 = true
}
sgrs := guest.OrderedSecurityGroupRules()
sgrs := guestnetwork.OrderedSecurityGroupRules(guest)
for _, sgr := range sgrs {
// kvm not support peer secgroup
acl, err := ruleToAcl(lportName, sgr, enableIPv6)