feature: support asymmmetric bandwidth limit (#24679)

Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
Jian Qiu
2026-04-16 15:15:43 +08:00
committed by GitHub
parent ee66577d94
commit 54309f95f3
22 changed files with 300 additions and 77 deletions
+6 -1
View File
@@ -144,7 +144,10 @@ func init() {
type ServerNetworkBWOptions struct {
SERVER string `help:"ID or Name of server"`
MACORIP string `help:"IP, Mac, or Index of NIC"`
BW int64 `help:"Bandwidth in Mbps"`
BW int64 `help:"Bandwidth in Mbps"`
Tx int64 `help:"Tx bandwidth in Mbps"`
Rx int64 `help:"Rx bandwidth in Mbps"`
}
R(&ServerNetworkBWOptions{}, "server-change-bandwidth", "Change server network bandwidth in Mbps", func(s *mcclient.ClientSession, args *ServerNetworkBWOptions) error {
params := jsonutils.NewDict()
@@ -162,6 +165,8 @@ func init() {
return fmt.Errorf("Please specify Ip or Mac")
}
params.Add(jsonutils.NewInt(args.BW), "bandwidth")
params.Add(jsonutils.NewInt(args.Tx), "tx_bw_limit")
params.Add(jsonutils.NewInt(args.Rx), "rx_bw_limit")
server, err := modules.Servers.PerformAction(s, args.SERVER, "change-bandwidth", params)
if err != nil {
return err
+2
View File
@@ -221,6 +221,8 @@ func init() {
params.Eip = opts.Eip
params.EipChargeType = billing_api.ParseNetChargeType(opts.EipChargeType)
params.EipBw = opts.EipBw
params.EipTxBw = opts.EipTxBw
params.EipRxBw = opts.EipRxBw
server, err := modules.Servers.Create(s, params.JSON(params))
if err != nil {
+6
View File
@@ -99,6 +99,8 @@ type NetworkConfig struct {
// 若指定镜像的网络驱动方式,此参数会被覆盖
Driver string `json:"driver"`
BwLimit int `json:"bw_limit"`
TxBwLimit int `json:"tx_bw_limit"`
RxBwLimit int `json:"rx_bw_limit"`
Vip bool `json:"vip"`
Reserved bool `json:"reserved"`
NumQueues int `json:"num_queues"`
@@ -644,6 +646,10 @@ type ServerCreateInput struct {
// 指定此参数后会创建新的弹性公网IP并绑定到新建的虚拟机
// 此参数优先级低于public_ip
EipBw int `json:"eip_bw,omitzero"`
// 弹性公网IP上行带宽
EipTxBw int `json:"eip_tx_bw,omitzero"`
// 弹性公网IP下行带宽
EipRxBw int `json:"eip_rx_bw,omitzero"`
// 弹性公网IP线路类型
EipBgpType string `json:"eip_bgp_type,omitzero"`
// 弹性公网IP计费类型
+25
View File
@@ -15,6 +15,8 @@
package compute
import (
"errors"
"yunion.io/x/onecloud/pkg/apis"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
)
@@ -152,3 +154,26 @@ type ElasticipRemoteUpdateInput struct {
// 是否覆盖替换所有标签
ReplaceTags *bool `json:"replace_tags" help:"replace all remote tags"`
}
type ElasticipChangeBandwidthInput struct {
// 带宽限制,单位mbps
// swagger:ignore
// Deprecated
Bandwidth int64 `json:"bandwidth" yunion-deprecated-by:"bandwidth_mb"`
// 带宽限制,单位mbps
BandwidthMb int64 `json:"bandwidth_mb"`
// 下行带宽限制,单位mbps
RxBwLimitMb int64 `json:"rx_bw_limit_mb"`
// 上行带宽限制,单位mbps
TxBwLimitMb int64 `json:"tx_bw_limit_mb"`
}
func (input ElasticipChangeBandwidthInput) Validate() error {
if input.BandwidthMb <= 0 && input.RxBwLimitMb <= 0 {
return errors.New("bandwidth_mb or rx_bw_limit_mb must be greater than 0")
}
if input.BandwidthMb <= 0 && input.TxBwLimitMb <= 0 {
return errors.New("bandwidth_mb or tx_bw_limit_mb must be greater than 0")
}
return nil
}
+2
View File
@@ -147,6 +147,8 @@ type GuestnetworkBaseDesc struct {
Masklen int8 `json:"masklen"`
Vlan int `json:"vlan"`
Bw int `json:"bw"`
RxBwLimit int `json:"rx_bw_limit"`
TxBwLimit int `json:"tx_bw_limit"`
Mtu int16 `json:"mtu"`
Index int `json:"index"`
RxTrafficLimit int64 `json:"rx_traffic_limit"`
+3
View File
@@ -1463,6 +1463,9 @@ type ServerChangeBandwidthInput struct {
Bandwidth int `json:"bandwidth"`
TxBwLimit int `json:"tx_bw_limit"`
RxBwLimit int `json:"rx_bw_limit"`
NoSync *bool `json:"no_sync"`
}
+2
View File
@@ -15,6 +15,8 @@
package compute
const (
TapConfigFileName = "tap-config.json"
HostVpcBridge = "__vpc_bridge__"
HostTapBridge = "__tap_bridge__"
HostLocalBridge = "brlocal"
+12
View File
@@ -376,6 +376,18 @@ func ParseNetworkConfig(desc string, idx int) (*compute.NetworkConfig, error) {
return nil, err
}
netConfig.BwLimit = bw
} else if strings.HasPrefix(p, "rx-bw=") {
bw, err := fileutils.GetSizeMb(p[len("rx-bw="):], 'M', 1000)
if err != nil {
return nil, err
}
netConfig.RxBwLimit = bw
} else if strings.HasPrefix(p, "tx-bw=") {
bw, err := fileutils.GetSizeMb(p[len("tx-bw="):], 'M', 1000)
if err != nil {
return nil, err
}
netConfig.TxBwLimit = bw
} else if p == "vip" {
netConfig.Vip = true
} else if strings.HasPrefix(p, "sriov-nic-id=") {
+2
View File
@@ -265,6 +265,8 @@ func (self *SBaremetalGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ct
Ip6Addr: address6,
NicDriver: netConfig.Driver,
BwLimit: netConfig.BwLimit,
RxBwLimit: netConfig.RxBwLimit,
TxBwLimit: netConfig.TxBwLimit,
Virtual: netConfig.Vip,
TryReserved: false,
AllocDir: api.IPAllocationStepup,
@@ -265,6 +265,8 @@ func (self *SCloudpodsBaremetalGuestDriver) Attach2RandomNetwork(guest *models.S
Ip6Addr: address6,
NicDriver: netConfig.Driver,
BwLimit: netConfig.BwLimit,
RxBwLimit: netConfig.RxBwLimit,
TxBwLimit: netConfig.TxBwLimit,
Virtual: netConfig.Vip,
TryReserved: false,
AllocDir: api.IPAllocationStepup,
@@ -204,6 +204,8 @@ func (self *SVirtualizedGuestDriver) Attach2RandomNetwork(guest *models.SGuest,
Ip6Addr: netConfig.Address6,
NicDriver: netConfig.Driver,
BwLimit: netConfig.BwLimit,
RxBwLimit: netConfig.RxBwLimit,
TxBwLimit: netConfig.TxBwLimit,
Virtual: netConfig.Vip,
TryReserved: netConfig.Reserved,
AllocDir: api.IPAllocationDefault,
+48 -19
View File
@@ -47,6 +47,7 @@ import (
"yunion.io/x/onecloud/pkg/compute/options"
"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/rbacutils"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
@@ -118,6 +119,11 @@ type SElasticip struct {
// 区域Id
// CloudregionId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
// 下行带宽限制,单位mbps
RxBwLimit int `nullable:"false" default:"0" list:"user"`
// 上行带宽限制,单位mbps
TxBwLimit int `nullable:"false" default:"0" list:"user"`
}
// 弹性公网IP列表
@@ -397,6 +403,8 @@ func (self *SElasticip) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
// desc.Add(jsonutils.NewString(self.ChargeType), "charge_type")
desc.Add(jsonutils.NewInt(int64(self.Bandwidth)), "bandwidth")
desc.Add(jsonutils.NewInt(int64(self.RxBwLimit)), "rx_bw_limit")
desc.Add(jsonutils.NewInt(int64(self.TxBwLimit)), "tx_bw_limit")
desc.Add(jsonutils.NewString(self.Mode), "mode")
desc.Add(jsonutils.NewString(self.IpAddr), "ip_addr")
desc.Add(jsonutils.NewString(self.BgpType), "bgp_type")
@@ -599,6 +607,8 @@ func (self *SElasticip) SyncWithCloudEip(ctx context.Context, userCred mcclient.
}
if bandwidth := ext.GetBandwidth(); bandwidth != 0 {
self.Bandwidth = bandwidth
self.RxBwLimit = bandwidth
self.TxBwLimit = bandwidth
}
self.IpAddr = ext.GetIpAddr()
self.Mode = ext.GetMode()
@@ -682,6 +692,8 @@ func (manager *SElasticipManager) newFromCloudEip(ctx context.Context, userCred
eip.ChargeType = billing_api.NET_CHARGE_TYPE_BY_TRAFFIC
}
eip.Bandwidth = extEip.GetBandwidth()
eip.RxBwLimit = extEip.GetBandwidth()
eip.TxBwLimit = extEip.GetBandwidth()
if networkId := extEip.GetINetworkId(); len(networkId) > 0 {
network, err := db.FetchByExternalIdAndManagerId(NetworkManager, networkId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
wire := WireManager.Query().SubQuery()
@@ -1625,6 +1637,8 @@ func (a SEipNetworks) Less(i, j int) bool {
type NewEipForVMOnHostArgs struct {
Bandwidth int
RxBwLimit int
TxBwLimit int
BgpType string
ChargeType billing_api.TNetChargeType
AutoDellocate bool
@@ -1640,7 +1654,6 @@ type NewEipForVMOnHostArgs struct {
func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCred mcclient.TokenCredential, args *NewEipForVMOnHostArgs) (*SElasticip, error) {
var (
bw = args.Bandwidth
bgpType = args.BgpType
chargeType = args.ChargeType
autoDellocate = args.AutoDellocate
@@ -1682,7 +1695,10 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
eip.Mode = api.EIP_MODE_STANDALONE_EIP
// do not implicitly auto dellocate EIP, should be set by user explicitly
// eip.AutoDellocate = tristate.True
eip.Bandwidth = bw
eip.Bandwidth = args.Bandwidth
eip.RxBwLimit = args.RxBwLimit
eip.TxBwLimit = args.TxBwLimit
eip.ChargeType = billing_api.TNetChargeType(chargeType)
eip.BgpType = args.BgpType
eip.AutoDellocate = tristate.NewFromBool(autoDellocate)
@@ -1845,14 +1861,13 @@ func (eip *SElasticip) AllocateAndAssociateInstance(ctx context.Context, userCre
return eip.startEipAllocateTask(ctx, userCred, params, parentTaskId)
}
func (self *SElasticip) PerformChangeBandwidth(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if self.Status != api.EIP_STATUS_READY {
return nil, httperrors.NewInvalidStatusError("cannot change bandwidth in status %s", self.Status)
func (self *SElasticip) PerformChangeBandwidth(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ElasticipChangeBandwidthInput) (jsonutils.JSONObject, error) {
if err := input.Validate(); err != nil {
return nil, httperrors.NewInputParameterError("%v", err)
}
bandwidth, err := data.Int("bandwidth")
if err != nil || bandwidth <= 0 {
return nil, httperrors.NewInputParameterError("Invalid bandwidth")
if self.Status != api.EIP_STATUS_READY {
return nil, httperrors.NewInvalidStatusError("cannot change bandwidth in status %s", self.Status)
}
if self.IsManaged() {
@@ -1861,24 +1876,23 @@ func (self *SElasticip) PerformChangeBandwidth(ctx context.Context, userCred mcc
return nil, err
}
if err := factory.ValidateChangeBandwidth(self.AssociateId, bandwidth); err != nil {
if err := factory.ValidateChangeBandwidth(self.AssociateId, input.BandwidthMb); err != nil {
return nil, httperrors.NewInputParameterError("%v", err)
}
}
err = self.StartEipChangeBandwidthTask(ctx, userCred, bandwidth)
err := self.StartEipChangeBandwidthTask(ctx, userCred, input)
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
return nil, nil
}
func (self *SElasticip) StartEipChangeBandwidthTask(ctx context.Context, userCred mcclient.TokenCredential, bandwidth int64) error {
func (self *SElasticip) StartEipChangeBandwidthTask(ctx context.Context, userCred mcclient.TokenCredential, input api.ElasticipChangeBandwidthInput) error {
self.SetStatus(ctx, userCred, api.EIP_STATUS_CHANGE_BANDWIDTH, "change bandwidth")
params := jsonutils.NewDict()
params.Add(jsonutils.NewInt(bandwidth), "bandwidth")
params := jsonutils.Marshal(input).(*jsonutils.JSONDict)
task, err := taskman.TaskManager.NewTask(ctx, "EipChangeBandwidthTask", self, userCred, params, "", "", nil)
if err != nil {
@@ -1889,24 +1903,35 @@ func (self *SElasticip) StartEipChangeBandwidthTask(ctx context.Context, userCre
return nil
}
func (self *SElasticip) DoChangeBandwidth(ctx context.Context, userCred mcclient.TokenCredential, bandwidth int) error {
func (self *SElasticip) DoChangeBandwidth(ctx context.Context, userCred mcclient.TokenCredential, input api.ElasticipChangeBandwidthInput) error {
changes := jsonutils.NewDict()
obw := api.ElasticipChangeBandwidthInput{
BandwidthMb: int64(self.Bandwidth),
RxBwLimitMb: int64(self.RxBwLimit),
TxBwLimitMb: int64(self.TxBwLimit),
}
changes.Add(jsonutils.NewInt(int64(self.Bandwidth)), "obw")
changes.Add(jsonutils.Marshal(obw), "obw_details")
_, err := db.Update(self, func() error {
self.Bandwidth = bandwidth
self.Bandwidth = int(input.BandwidthMb)
self.RxBwLimit = int(input.RxBwLimitMb)
self.TxBwLimit = int(input.TxBwLimitMb)
return nil
})
self.SetStatus(ctx, userCred, api.EIP_STATUS_READY, "finish change bandwidth")
if err != nil {
self.SetStatus(ctx, userCred, api.EIP_STATUS_READY, "change bandwidth failed")
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CHANGE_BANDWIDTH, changes, userCred, false)
log.Errorf("DoChangeBandwidth update fail %s", err)
return err
}
changes.Add(jsonutils.NewInt(int64(bandwidth)), "nbw")
self.SetStatus(ctx, userCred, api.EIP_STATUS_READY, "finish change bandwidth")
changes.Add(jsonutils.NewInt(int64(input.BandwidthMb)), "nbw")
changes.Add(jsonutils.Marshal(input), "nbw_details")
db.OpsLog.LogEvent(self, db.ACT_CHANGE_BANDWIDTH, changes, userCred)
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CHANGE_BANDWIDTH, changes, userCred, true)
return nil
}
@@ -1916,6 +1941,8 @@ type EipUsage struct {
PublicIpBandwidth int
EIPCount int
EipBandwidth int
EipRxBwLimit int
EipTxBwLimit int
EIPUsedCount int
}
@@ -1962,6 +1989,8 @@ func (manager *SElasticipManager) TotalCount(
q2 := q2sq.Query(
sqlchemy.COUNT("eip_count", q2sq.Field("id")),
sqlchemy.SUM("eip_bandwidth", q2sq.Field("bandwidth")),
sqlchemy.SUM("eip_rx_bw_limit", q2sq.Field("rx_bw_limit")),
sqlchemy.SUM("eip_tx_bw_limit", q2sq.Field("tx_bw_limit")),
).Equals("mode", api.EIP_MODE_STANDALONE_EIP)
q2 = manager.usageQ(ctx, scope, ownerId, q2, rangeObjs, providers, brands, cloudEnv, policyResult)
q3sq := manager.Query().SubQuery()
+18 -5
View File
@@ -781,6 +781,8 @@ func (self *SGuest) PerformClone(ctx context.Context, userCred mcclient.TokenCre
createInput.AutoStart = cloneInput.AutoStart
createInput.EipBw = cloneInput.EipBw
createInput.EipTxBw = cloneInput.EipTxBw
createInput.EipRxBw = cloneInput.EipRxBw
createInput.Eip = cloneInput.Eip
createInput.EipChargeType = cloneInput.EipChargeType
if err := GuestManager.validateEip(ctx, userCred, createInput, createInput.PreferRegion, createInput.PreferManager); err != nil {
@@ -2831,6 +2833,12 @@ func (self *SGuest) PerformChangeIpaddr(
if conf.BwLimit == 0 {
conf.BwLimit = gn.BwLimit
}
if conf.TxBwLimit == 0 {
conf.TxBwLimit = gn.TxBwLimit
}
if conf.RxBwLimit == 0 {
conf.RxBwLimit = gn.RxBwLimit
}
if conf.Index == 0 {
conf.Index = int(gn.Index)
}
@@ -3365,9 +3373,8 @@ func (guest *SGuest) PerformChangeBandwidth(
return nil, httperrors.NewBadRequestError("Cannot change bandwidth in status %s", guest.Status)
}
bandwidth := input.Bandwidth
if bandwidth < 0 {
return nil, httperrors.NewBadRequestError("Bandwidth must be non-negative")
if input.Bandwidth < 0 && input.TxBwLimit < 0 && input.RxBwLimit < 0 {
return nil, httperrors.NewBadRequestError("Bandwidth, tx_bw_limit and rx_bw_limit must be non-negative")
}
guestnic, err := guest.findGuestnetworkByInfo(input.ServerNetworkInfo)
@@ -3375,10 +3382,14 @@ func (guest *SGuest) PerformChangeBandwidth(
return nil, errors.Wrap(err, "findGuestnetworkByInfo")
}
if guestnic.BwLimit != int(bandwidth) {
if guestnic.BwLimit != int(input.Bandwidth) || guestnic.TxBwLimit != int(input.TxBwLimit) || guestnic.RxBwLimit != int(input.RxBwLimit) {
oldBw := guestnic.BwLimit
oldTxBw := guestnic.TxBwLimit
oldRxBw := guestnic.RxBwLimit
_, err := db.Update(guestnic, func() error {
guestnic.BwLimit = int(bandwidth)
guestnic.BwLimit = int(input.Bandwidth)
guestnic.TxBwLimit = int(input.TxBwLimit)
guestnic.RxBwLimit = int(input.RxBwLimit)
return nil
})
if err != nil {
@@ -3386,6 +3397,8 @@ func (guest *SGuest) PerformChangeBandwidth(
}
eventDesc := guestnic.GetShortDesc(ctx)
eventDesc.Add(jsonutils.NewInt(int64(oldBw)), "old_bw_limit_mbps")
eventDesc.Add(jsonutils.NewInt(int64(oldTxBw)), "old_tx_bw_limit_mbps")
eventDesc.Add(jsonutils.NewInt(int64(oldRxBw)), "old_rx_bw_limit_mbps")
db.OpsLog.LogEvent(guest, db.ACT_CHANGE_BANDWIDTH, eventDesc, userCred)
logclient.AddActionLogWithContext(ctx, guest, logclient.ACT_VM_CHANGE_BANDWIDTH, eventDesc, userCred, true)
if guest.Status == api.VM_READY || (input.NoSync != nil && *input.NoSync) {
+44
View File
@@ -127,6 +127,11 @@ type SGuestnetwork struct {
SBillingTypeBase `billing_type->default:"prepaid"`
SBillingChargeTypeBase `charge_type->default:"bandwidth"`
// 下行带宽限制,单位mbps
RxBwLimit int `nullable:"false" default:"0" list:"user"`
// 上行带宽限制,单位mbps
TxBwLimit int `nullable:"false" default:"0" list:"user"`
}
func (gn SGuestnetwork) GetIP() string {
@@ -271,6 +276,8 @@ type newGuestNetworkArgs struct {
ifname string
macAddr string
bwLimit int
rxBwLimit int
txBwLimit int
nicDriver string
numQueues int
teamWithMac string
@@ -301,6 +308,8 @@ func (manager *SGuestnetworkManager) newGuestNetwork(
driver = args.nicDriver
numQueues = args.numQueues
bwLimit = args.bwLimit
rxBwLimit = args.rxBwLimit
txBwLimit = args.txBwLimit
virtual = args.virtual
reserved = args.tryReserved
allocDir = args.allocDir
@@ -329,6 +338,12 @@ func (manager *SGuestnetworkManager) newGuestNetwork(
if bwLimit >= 0 {
gn.BwLimit = bwLimit
}
if rxBwLimit >= 0 {
gn.RxBwLimit = rxBwLimit
}
if txBwLimit >= 0 {
gn.TxBwLimit = txBwLimit
}
gn.PortMappings = args.portMappings
gn.BillingType = args.billingType
@@ -723,6 +738,8 @@ func (gn *SGuestnetwork) getJsonDesc() *api.GuestnetworkJsonDesc {
desc.TxTrafficLimit = gn.TxTrafficLimit
desc.Vlan = net.VlanId
desc.Bw = gn.getBandwidth(net, wire)
desc.RxBwLimit = gn.getRxBwLimit(net, wire)
desc.TxBwLimit = gn.getTxBwLimit(net, wire)
desc.Mtu = gn.getMtu(net, wire)
desc.Index = gn.Index
desc.VirtualIps = gn.GetVirtualIPs()
@@ -906,6 +923,8 @@ func (gn *SGuestnetwork) GetDetailedString() string {
network.Name,
gn.Driver,
fmt.Sprintf("%d", gn.getBandwidth(network, nil)),
fmt.Sprintf("rx%d", gn.getRxBwLimit(network, nil)),
fmt.Sprintf("tx%d", gn.getTxBwLimit(network, nil)),
fmt.Sprintf("%d", naCount),
)
return fmt.Sprintf("eth%d:%s", gn.Index, strings.Join(parts, "/"))
@@ -1113,7 +1132,11 @@ type GuestnicsCount struct {
ExternalNicCount int
ExternalVirtualNicCount int
InternalBandwidth int
InternalRxBwLimit int
InternalTxBwLimit int
ExternalBandwidth int
ExternalRxBwLimit int
ExternalTxBwLimit int
}
func calculateNics(q *sqlchemy.SQuery) GuestnicsCount {
@@ -1131,6 +1154,8 @@ func calculateNics(q *sqlchemy.SQuery) GuestnicsCount {
cnt.ExternalNicCount += 1
}
cnt.ExternalBandwidth += gn.BwLimit
cnt.ExternalRxBwLimit += gn.RxBwLimit
cnt.ExternalTxBwLimit += gn.TxBwLimit
} else {
if gn.Virtual {
cnt.InternalVirtualNicCount += 1
@@ -1138,6 +1163,8 @@ func calculateNics(q *sqlchemy.SQuery) GuestnicsCount {
cnt.InternalNicCount += 1
}
cnt.InternalBandwidth += gn.BwLimit
cnt.InternalRxBwLimit += gn.RxBwLimit
cnt.InternalTxBwLimit += gn.TxBwLimit
}
}
return cnt
@@ -1181,6 +1208,20 @@ func (gn *SGuestnetwork) getBandwidth(net *SNetwork, wire *SWire) int {
}
}
func (gn *SGuestnetwork) getRxBwLimit(net *SNetwork, wire *SWire) int {
if gn.RxBwLimit > 0 && gn.RxBwLimit <= api.MAX_BANDWIDTH {
return gn.RxBwLimit
}
return gn.getBandwidth(net, wire)
}
func (gn *SGuestnetwork) getTxBwLimit(net *SNetwork, wire *SWire) int {
if gn.TxBwLimit > 0 && gn.TxBwLimit <= api.MAX_BANDWIDTH {
return gn.TxBwLimit
}
return gn.getBandwidth(net, wire)
}
func (gn *SGuestnetwork) getMtu(net *SNetwork, wire *SWire) int16 {
return net.getMtu(wire)
}
@@ -1430,6 +1471,9 @@ func (gn *SGuestnetwork) ToNetworkConfig() *api.NetworkConfig {
Ifname: gn.Ifname,
NetType: net.ServerType,
Exit: net.IsExitNetwork(),
RxBwLimit: gn.RxBwLimit,
TxBwLimit: gn.TxBwLimit,
}
return ret
}
+20 -3
View File
@@ -2548,8 +2548,7 @@ func (manager *SGuestManager) validateEip(ctx context.Context, userCred mcclient
return nil
}
eipStr := input.Eip
eipBw := input.EipBw
if len(eipStr) > 0 || eipBw > 0 {
if len(eipStr) > 0 || input.EipTxBw > 0 || input.EipRxBw > 0 || input.EipBw > 0 {
if !driver.IsSupportEip() {
return httperrors.NewNotImplementedError("eip not supported for %s", input.Hypervisor)
}
@@ -2710,7 +2709,9 @@ func getGuestResourceRequirements(
eipCnt := 0
eipBw := input.EipBw
if eipBw > 0 {
eipTxBw := input.EipTxBw
eipRxBw := input.EipRxBw
if eipBw > 0 || eipTxBw > 0 || eipRxBw > 0 {
eipCnt = 1
}
@@ -3869,6 +3870,8 @@ type Attach2NetworkArgs struct {
StrictIPv6 bool
BwLimit int
RxBwLimit int
TxBwLimit int
NicDriver string
NumQueues int
RxTrafficLimit int64
@@ -3903,6 +3906,8 @@ func (args *Attach2NetworkArgs) onceArgs(i int) attach2NetworkOnceArgs {
strictIPv6: args.StrictIPv6,
bwLimit: args.BwLimit,
rxBwLimit: args.RxBwLimit,
txBwLimit: args.TxBwLimit,
nicDriver: args.NicDriver,
numQueues: args.NumQueues,
txTrafficLimit: args.TxTrafficLimit,
@@ -3949,6 +3954,8 @@ type attach2NetworkOnceArgs struct {
strictIPv6 bool
bwLimit int
rxBwLimit int
txBwLimit int
nicDriver string
numQueues int
nicConf SNicConfig
@@ -4033,6 +4040,8 @@ func (self *SGuest) attach2NetworkOnce(
ifname: args.nicConf.Ifname,
macAddr: args.nicConf.Mac,
bwLimit: args.bwLimit,
rxBwLimit: args.rxBwLimit,
txBwLimit: args.txBwLimit,
nicDriver: nicDriver,
numQueues: args.numQueues,
teamWithMac: args.teamWithMac,
@@ -4852,6 +4861,8 @@ func (self *SGuest) attach2NamedNetworkDesc(ctx context.Context, userCred mcclie
NicDriver: netConfig.Driver,
NumQueues: netConfig.NumQueues,
BwLimit: netConfig.BwLimit,
RxBwLimit: netConfig.RxBwLimit,
TxBwLimit: netConfig.TxBwLimit,
RxTrafficLimit: netConfig.RxTrafficLimit,
TxTrafficLimit: netConfig.TxTrafficLimit,
Virtual: netConfig.Vip,
@@ -6874,6 +6885,8 @@ func (self *SGuest) ToCreateInput(ctx context.Context, userCred mcclient.TokenCr
userInput.SecgroupId = genInput.SecgroupId
userInput.KeypairId = genInput.KeypairId
userInput.EipBw = genInput.EipBw
userInput.EipTxBw = genInput.EipTxBw
userInput.EipRxBw = genInput.EipRxBw
userInput.EipChargeType = genInput.EipChargeType
drv, _ := self.GetDriver()
if drv != nil && drv.IsSupportPublicIp() {
@@ -6948,6 +6961,8 @@ func (self *SGuest) toCreateInput() *api.ServerCreateInput {
switch eip.Mode {
case api.EIP_MODE_STANDALONE_EIP:
r.EipBw = eip.Bandwidth
r.EipTxBw = eip.TxBwLimit
r.EipRxBw = eip.RxBwLimit
r.EipChargeType = eip.ChargeType
case api.EIP_MODE_INSTANCE_PUBLICIP:
drv, _ := self.GetDriver()
@@ -7032,6 +7047,8 @@ func (self *SGuest) ToNetworksConfig() []*api.NetworkConfig {
// netConf.Reserved
netConf.Driver = guestNetwork.Driver
netConf.BwLimit = guestNetwork.BwLimit
netConf.RxBwLimit = guestNetwork.RxBwLimit
netConf.TxBwLimit = guestNetwork.TxBwLimit
netConf.RequireTeaming = requireTeaming
// netConf.NetType
ret = append(ret, netConf)
+4
View File
@@ -26,6 +26,10 @@ import (
)
func (h *SHost) GetDetailsTapConfig(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (api.SHostTapConfig, error) {
return h.getTapConfig()
}
func (h *SHost) getTapConfig() (api.SHostTapConfig, error) {
conf := api.SHostTapConfig{}
srvs, err := NetTapServiceManager.getEnabledTapServiceOnHost(h.Id)
+7
View File
@@ -5431,6 +5431,13 @@ func (hh *SHost) PerformPing(ctx context.Context, userCred mcclient.TokenCredent
return nil, errors.Wrap(err, "get host files")
}
result.Set("host_files", jsonutils.Marshal(hostFiles))
// get tap config
tapConfig, err := hh.getTapConfig()
if err != nil {
log.Errorf("get tap config error %s", err)
} else {
result.Set("tap_config", jsonutils.Marshal(tapConfig))
}
appParams := appsrv.AppContextGetParams(ctx)
if appParams != nil {
@@ -44,9 +44,10 @@ func (self *EipChangeBandwidthTask) TaskFail(ctx context.Context, eip *models.SE
func (self *EipChangeBandwidthTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
eip := obj.(*models.SElasticip)
bandwidth, _ := self.Params.Int("bandwidth")
if bandwidth <= 0 {
self.TaskFail(ctx, eip, errors.Errorf("nvalid bandwidth %d", bandwidth))
input := api.ElasticipChangeBandwidthInput{}
err := self.Params.Unmarshal(&input)
if err != nil {
self.TaskFail(ctx, eip, errors.Wrapf(err, "Unmarshal"))
return
}
@@ -57,15 +58,14 @@ func (self *EipChangeBandwidthTask) OnInit(ctx context.Context, obj db.IStandalo
return
}
err = extEip.ChangeBandwidth(int(bandwidth))
err = extEip.ChangeBandwidth(int(input.BandwidthMb))
if err != nil {
self.TaskFail(ctx, eip, errors.Wrapf(err, "ChangeBandwidth"))
return
}
}
if err := eip.DoChangeBandwidth(ctx, self.UserCred, int(bandwidth)); err != nil {
if err := eip.DoChangeBandwidth(ctx, self.UserCred, input); err != nil {
self.TaskFail(ctx, eip, errors.Wrapf(err, "DoChangeBandwidth"))
return
}
@@ -195,13 +195,15 @@ func (task *GuestBatchCreateTask) allocateGuestOnHost(ctx context.Context, guest
}
if input.PublicIpBw > 0 {
input.Eip, input.EipBw = "", 0
input.Eip, input.EipBw, input.EipTxBw, input.EipRxBw = "", 0, 0, 0
}
// allocate eips
if input.EipBw > 0 {
eip, err := models.ElasticipManager.NewEipForVMOnHost(ctx, task.UserCred, &models.NewEipForVMOnHostArgs{
Bandwidth: input.EipBw,
TxBwLimit: input.EipTxBw,
RxBwLimit: input.EipRxBw,
BgpType: input.EipBgpType,
ChargeType: input.EipChargeType,
AutoDellocate: input.EipAutoDellocate,
@@ -16,6 +16,8 @@ package hostpinger
import (
"context"
"os"
"path/filepath"
"time"
"github.com/shirou/gopsutil/cpu"
@@ -175,6 +177,16 @@ func (p *SHostPingTask) ping(div int, hostId string) error {
log.Errorf("on host files changed failed %s", err)
}
}
if res.Contains("tap_config") {
tapConfJson, err := res.Get("tap_config")
if err != nil {
log.Errorf("get tap config from res %s: %v", res.String(), err)
} else {
tagConfPath := filepath.Join(options.HostOptions.ServersPath, api.TapConfigFileName)
os.WriteFile(tagConfPath, []byte(tapConfJson.String()), 0644)
}
}
}
return nil
}
+6
View File
@@ -438,6 +438,8 @@ type ServerCreateFromInstanceSnapshot struct {
AllowDelete bool `help:"Unlock server to allow deleting"`
EipBw int `help:"allocate EIP with bandwidth in MB when server is created" json:"eip_bw,omitzero"`
EipTxBw int `help:"allocate EIP with上行带宽 in MB when server is created" json:"eip_tx_bw,omitzero"`
EipRxBw int `help:"allocate EIP with下行带宽 in MB when server is created" json:"eip_rx_bw,omitzero"`
EipChargeType string `help:"newly allocated EIP charge type" choices:"traffic|bandwidth" json:"eip_charge_type,omitempty"`
Eip string `help:"associate with an existing EIP when server is created" json:"eip,omitempty"`
}
@@ -504,6 +506,8 @@ type ServerCreateOptionalOptions struct {
GenerateName bool `help:"name is generated by pattern" json:"-"`
EipBw int `help:"allocate EIP with bandwidth in MB when server is created" json:"eip_bw,omitzero"`
EipTxBw int `help:"allocate EIP with上行带宽 in MB when server is created" json:"eip_tx_bw,omitzero"`
EipRxBw int `help:"allocate EIP with下行带宽 in MB when server is created" json:"eip_rx_bw,omitzero"`
EipBgpType string `help:"desired BGP type of newly alloated EIP" json:"eip_bgp_type,omitzero"`
EipChargeType string `help:"newly allocated EIP charge type" choices:"traffic|bandwidth" json:"eip_charge_type,omitempty"`
Eip string `help:"associate with an existing EIP when server is created" json:"eip,omitempty"`
@@ -592,6 +596,8 @@ func (opts *ServerCreateOptionalOptions) OptionalParams() (*computeapi.ServerCre
AutoRenew: opts.AutoRenew,
AutoPrepaidRecycle: opts.AutoPrepaidRecycle,
EipBw: opts.EipBw,
EipTxBw: opts.EipTxBw,
EipRxBw: opts.EipRxBw,
EipBgpType: opts.EipBgpType,
EipChargeType: billing_api.TNetChargeType(opts.EipChargeType),
PublicIpBw: opts.PublicIpBw,
+68 -42
View File
@@ -705,19 +705,25 @@ func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestn
}
var qosVif []*ovn_nb.QoS
if bwMbps := guestnetwork.BwLimit; bwMbps > 0 {
var (
kbps = int64(bwMbps * 1000)
kbur = int64(kbps * 2)
)
if guestnetwork.BwLimit > 0 || guestnetwork.RxBwLimit > 0 || guestnetwork.TxBwLimit > 0 {
kbpsRx := int64(guestnetwork.RxBwLimit * 1000)
if kbpsRx == 0 {
kbpsRx = int64(guestnetwork.BwLimit * 1000)
}
kburRx := int64(kbpsRx * 2)
kbpsTx := int64(guestnetwork.TxBwLimit * 1000)
if kbpsTx == 0 {
kbpsTx = int64(guestnetwork.BwLimit * 1000)
}
kburTx := int64(kbpsTx * 2)
qosVif = []*ovn_nb.QoS{
{
Priority: 2000,
Direction: "from-lport",
Match: fmt.Sprintf("inport == %q", lportName),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
"rate": kbpsTx,
"burst": kburTx,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosRef,
@@ -728,8 +734,8 @@ func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestn
Direction: "to-lport",
Match: fmt.Sprintf("outport == %q", lportName),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
"rate": kbpsRx,
"burst": kburRx,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosRef,
@@ -757,20 +763,27 @@ func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestn
externalKeyOcRef: ocGnrDefaultRef,
},
}
if bwMbps := eip.Bandwidth; bwMbps > 0 {
var (
kbps = int64(bwMbps * 1000)
kbur = int64(kbps * 2)
eipgwVip = apis.VpcEipGatewayIP3().String()
)
if eip.Bandwidth > 0 || eip.TxBwLimit > 0 || eip.RxBwLimit > 0 {
kbpsTx := int64(eip.TxBwLimit * 1000)
if kbpsTx == 0 {
kbpsTx = int64(eip.Bandwidth * 1000)
}
kburTx := int64(kbpsTx * 2)
kbpsRx := int64(eip.RxBwLimit * 1000)
if kbpsRx == 0 {
kbpsRx = int64(eip.Bandwidth * 1000)
}
kburRx := int64(kbpsRx * 2)
eipgwVip := apis.VpcEipGatewayIP3().String()
hasQoSEip = true
qosEipIn = &ovn_nb.QoS{
Priority: 2000,
Direction: "from-lport",
Direction: "to-lport",
Match: fmt.Sprintf("inport == %q && ip4 && ip4.dst == %s", vpcEipLspName(vpc.Id, eipgwVip), guestnetwork.IpAddr),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
"rate": kbpsRx,
"burst": kburRx,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosEipRef,
@@ -781,8 +794,8 @@ func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestn
Direction: "from-lport",
Match: fmt.Sprintf("inport == %q && ip4 && ip4.src == %s", vpcErpName(vpc.Id), guestnetwork.IpAddr),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
"rate": kbpsTx,
"burst": kburTx,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosEipRef,
@@ -971,20 +984,27 @@ func (keeper *OVNNorthboundKeeper) ClaimLoadbalancerNetwork(ctx context.Context,
externalKeyOcRef: ocLnrDefaultRef,
},
}
if bwMbps := eip.Bandwidth; bwMbps > 0 {
var (
kbps = int64(bwMbps * 1000)
kbur = int64(kbps * 2)
eipgwVip = apis.VpcEipGatewayIP3().String()
)
if eip.Bandwidth > 0 || eip.TxBwLimit > 0 || eip.RxBwLimit > 0 {
kbpsTx := int64(eip.TxBwLimit * 1000)
if kbpsTx == 0 {
kbpsTx = int64(eip.Bandwidth * 1000)
}
kburTx := int64(kbpsTx * 2)
kbpsRx := int64(eip.RxBwLimit * 1000)
if kbpsRx == 0 {
kbpsRx = int64(eip.Bandwidth * 1000)
}
kburRx := int64(kbpsRx * 2)
eipgwVip := apis.VpcEipGatewayIP3().String()
hasQoSEip = true
qosEipIn = &ovn_nb.QoS{
Priority: 2000,
Direction: "from-lport",
Direction: "to-lport",
Match: fmt.Sprintf("inport == %q && ip4 && ip4.dst == %s", vpcEipLspName(vpcId, eipgwVip), lbIntIp),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
"rate": kbpsRx,
"burst": kburRx,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosEipRef,
@@ -995,8 +1015,8 @@ func (keeper *OVNNorthboundKeeper) ClaimLoadbalancerNetwork(ctx context.Context,
Direction: "from-lport",
Match: fmt.Sprintf("inport == %q", lportName),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
"rate": kbpsTx,
"burst": kburTx,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosEipRef,
@@ -1208,20 +1228,26 @@ func (keeper *OVNNorthboundKeeper) ClaimGroupnetwork(ctx context.Context, groupn
externalKeyOcRef: ocGnrDefaultRef,
},
}
if bwMbps := eip.Bandwidth; bwMbps > 0 {
var (
kbps = int64(bwMbps * 1000)
kbur = int64(kbps * 2)
eipgwVip = apis.VpcEipGatewayIP3().String()
)
if eip.Bandwidth > 0 || eip.TxBwLimit > 0 || eip.RxBwLimit > 0 {
kbpsTx := int64(eip.TxBwLimit * 1000)
if kbpsTx == 0 {
kbpsTx = int64(eip.Bandwidth * 1000)
}
kburTx := int64(kbpsTx * 2)
kbpsRx := int64(eip.RxBwLimit * 1000)
if kbpsRx == 0 {
kbpsRx = int64(eip.Bandwidth * 1000)
}
kburRx := int64(kbpsRx * 2)
eipgwVip := apis.VpcEipGatewayIP3().String()
hasQoSEip = true
qosEipIn = &ovn_nb.QoS{
Priority: 2000,
Direction: "from-lport",
Direction: "to-lport",
Match: fmt.Sprintf("inport == %q && ip4 && ip4.dst == %s", vpcEipLspName(vpc.Id, eipgwVip), groupnetwork.IpAddr),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
"rate": kbpsRx,
"burst": kburRx,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosEipRef,
@@ -1232,8 +1258,8 @@ func (keeper *OVNNorthboundKeeper) ClaimGroupnetwork(ctx context.Context, groupn
Direction: "from-lport",
Match: fmt.Sprintf("inport == %q && ip4 && ip4.src == %s", vpcErpName(vpc.Id), groupnetwork.IpAddr),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
"rate": kbpsTx,
"burst": kburTx,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosEipRef,