2023-03-16 20:05:39 +01:00
package limits
import (
2023-03-21 19:06:23 +01:00
"github.com/jmoiron/sqlx"
2023-03-27 21:29:25 +02:00
"github.com/openziti/zrok/controller/emailUi"
2023-03-16 20:05:39 +01:00
"github.com/openziti/zrok/controller/metrics"
"github.com/openziti/zrok/controller/store"
"github.com/openziti/zrok/controller/zrokEdgeSdk"
2024-05-23 20:08:14 +02:00
"github.com/openziti/zrok/sdk/golang/sdk"
2024-06-11 18:00:12 +02:00
"github.com/openziti/zrok/util"
2023-03-21 19:06:23 +01:00
"github.com/pkg/errors"
2023-03-16 20:05:39 +01:00
"github.com/sirupsen/logrus"
2023-03-28 20:39:42 +02:00
"reflect"
2023-03-17 18:13:33 +01:00
"time"
2023-03-16 20:05:39 +01:00
)
type Agent struct {
2024-06-03 19:37:32 +02:00
cfg * Config
ifx * influxReader
zCfg * zrokEdgeSdk . Config
str * store . Store
queue chan * metrics . Usage
warningActions [ ] AccountAction
limitActions [ ] AccountAction
relaxActions [ ] AccountAction
close chan struct { }
join chan struct { }
2023-03-16 20:05:39 +01:00
}
2023-03-27 21:29:25 +02:00
func NewAgent ( cfg * Config , ifxCfg * metrics . InfluxConfig , zCfg * zrokEdgeSdk . Config , emailCfg * emailUi . Config , str * store . Store ) ( * Agent , error ) {
2023-03-27 17:34:29 +02:00
a := & Agent {
2024-06-03 19:37:32 +02:00
cfg : cfg ,
ifx : newInfluxReader ( ifxCfg ) ,
zCfg : zCfg ,
str : str ,
queue : make ( chan * metrics . Usage , 1024 ) ,
2024-06-04 16:33:39 +02:00
warningActions : [ ] AccountAction { newWarningAction ( emailCfg , str ) } ,
limitActions : [ ] AccountAction { newLimitAction ( str , zCfg ) } ,
relaxActions : [ ] AccountAction { newRelaxAction ( str , zCfg ) } ,
2024-06-03 19:37:32 +02:00
close : make ( chan struct { } ) ,
join : make ( chan struct { } ) ,
2023-03-27 17:34:29 +02:00
}
return a , nil
2023-03-16 20:05:39 +01:00
}
2023-03-17 18:13:33 +01:00
func ( a * Agent ) Start ( ) {
go a . run ( )
2023-03-16 20:05:39 +01:00
}
func ( a * Agent ) Stop ( ) {
2023-03-17 18:13:33 +01:00
close ( a . close )
<- a . join
2023-03-16 20:05:39 +01:00
}
2023-03-21 21:34:45 +01:00
func ( a * Agent ) CanCreateEnvironment ( acctId int , trx * sqlx . Tx ) ( bool , error ) {
2023-03-29 19:29:12 +02:00
if a . cfg . Enforcing {
2024-05-15 21:48:42 +02:00
if err := a . str . LimitCheckLock ( acctId , trx ) ; err != nil {
return false , err
}
2024-06-04 22:27:05 +02:00
2024-06-06 20:00:49 +02:00
ul , err := a . getUserLimits ( acctId , trx )
2024-06-04 22:27:05 +02:00
if err != nil {
return false , err
}
2023-03-29 19:29:12 +02:00
2024-06-06 20:00:49 +02:00
if ul . resource . GetEnvironments ( ) > store . Unlimited {
2023-03-29 19:29:12 +02:00
envs , err := a . str . FindEnvironmentsForAccount ( acctId , trx )
if err != nil {
return false , err
}
2024-07-09 17:37:29 +02:00
if len ( envs ) + 1 > ul . resource . GetEnvironments ( ) {
2023-03-29 19:29:12 +02:00
return false , nil
}
}
2023-03-21 21:34:45 +01:00
}
2024-06-04 22:43:38 +02:00
2023-03-21 21:34:45 +01:00
return true , nil
}
2023-03-21 21:18:17 +01:00
2024-06-07 16:21:26 +02:00
func ( a * Agent ) CanCreateShare ( acctId , envId int , reserved , uniqueName bool , _ sdk . ShareMode , backendMode sdk . BackendMode , trx * sqlx . Tx ) ( bool , error ) {
2023-03-29 19:29:12 +02:00
if a . cfg . Enforcing {
2024-05-15 21:48:42 +02:00
if err := a . str . LimitCheckLock ( acctId , trx ) ; err != nil {
return false , err
}
2024-06-04 22:43:38 +02:00
2024-06-07 16:21:26 +02:00
ul , err := a . getUserLimits ( acctId , trx )
2024-06-04 22:43:38 +02:00
if err != nil {
return false , err
}
2024-06-07 19:29:51 +02:00
if scopedBwc , found := ul . scopes [ backendMode ] ; found {
latestScopedJe , err := a . isBandwidthClassLimitedForAccount ( acctId , scopedBwc , trx )
2024-06-07 17:38:49 +02:00
if err != nil {
return false , err
2024-06-04 22:43:38 +02:00
}
2024-06-07 19:29:51 +02:00
if latestScopedJe != nil {
2024-06-07 17:38:49 +02:00
return false , nil
2023-03-29 19:29:12 +02:00
}
2024-06-07 19:29:51 +02:00
} else {
for _ , bwc := range ul . bandwidth {
latestJe , err := a . isBandwidthClassLimitedForAccount ( acctId , bwc , trx )
if err != nil {
return false , err
}
if latestJe != nil {
return false , nil
}
}
2023-03-21 21:18:17 +01:00
}
2023-03-29 19:29:12 +02:00
2024-06-07 21:05:18 +02:00
rc := ul . resource
if scopeRc , found := ul . scopes [ backendMode ] ; found {
rc = scopeRc
}
if rc . GetShares ( ) > store . Unlimited || ( reserved && rc . GetReservedShares ( ) > store . Unlimited ) || ( reserved && uniqueName && rc . GetUniqueNames ( ) > store . Unlimited ) {
2023-03-29 19:29:12 +02:00
envs , err := a . str . FindEnvironmentsForAccount ( acctId , trx )
if err != nil {
return false , err
}
total := 0
2024-05-22 22:21:52 +02:00
reserveds := 0
uniqueNames := 0
2023-03-29 19:29:12 +02:00
for i := range envs {
shrs , err := a . str . FindSharesForEnvironment ( envs [ i ] . Id , trx )
if err != nil {
return false , errors . Wrapf ( err , "unable to find shares for environment '%v'" , envs [ i ] . ZId )
}
total += len ( shrs )
2024-05-22 22:21:52 +02:00
for _ , shr := range shrs {
if shr . Reserved {
reserveds ++
}
if shr . UniqueName {
uniqueNames ++
}
}
2024-06-25 22:09:51 +02:00
if rc . GetShares ( ) > store . Unlimited && total + 1 > rc . GetShares ( ) {
2024-06-11 18:00:12 +02:00
logrus . Debugf ( "account '#%d', environment '%d' over shares limit '%d'" , acctId , envId , a . cfg . Shares )
2023-03-29 19:29:12 +02:00
return false , nil
}
2024-06-25 22:09:51 +02:00
if reserved && rc . GetReservedShares ( ) > store . Unlimited && reserveds + 1 > rc . GetReservedShares ( ) {
2024-06-11 18:00:12 +02:00
logrus . Debugf ( "account '#%d', environment '%d' over reserved shares limit '%d'" , acctId , envId , a . cfg . ReservedShares )
2024-05-22 22:21:52 +02:00
return false , nil
}
2024-06-25 22:09:51 +02:00
if reserved && uniqueName && rc . GetUniqueNames ( ) > store . Unlimited && uniqueNames + 1 > rc . GetUniqueNames ( ) {
2024-06-11 18:00:12 +02:00
logrus . Debugf ( "account '#%d', environment '%d' over unique names limit '%d'" , acctId , envId , a . cfg . UniqueNames )
2024-05-22 22:21:52 +02:00
return false , nil
}
2023-03-29 19:29:12 +02:00
}
2023-03-21 21:18:17 +01:00
}
}
return true , nil
}
2023-06-06 17:29:22 +02:00
func ( a * Agent ) CanAccessShare ( shrId int , trx * sqlx . Tx ) ( bool , error ) {
if a . cfg . Enforcing {
shr , err := a . str . GetShare ( shrId , trx )
if err != nil {
return false , err
}
2024-06-04 22:50:08 +02:00
env , err := a . str . GetEnvironment ( shr . EnvironmentId , trx )
if err != nil {
return false , err
}
if env . AccountId != nil {
2024-06-17 18:12:38 +02:00
if err := a . str . LimitCheckLock ( * env . AccountId , trx ) ; err != nil {
return false , err
}
2024-06-07 16:21:26 +02:00
ul , err := a . getUserLimits ( * env . AccountId , trx )
2023-06-06 17:29:22 +02:00
if err != nil {
return false , err
}
2024-06-04 22:50:08 +02:00
2024-06-17 18:12:38 +02:00
if scopedBwc , found := ul . scopes [ sdk . BackendMode ( shr . BackendMode ) ] ; found {
latestScopedJe , err := a . isBandwidthClassLimitedForAccount ( * env . AccountId , scopedBwc , trx )
if err != nil {
return false , err
}
if latestScopedJe != nil {
return false , nil
2024-06-04 22:50:08 +02:00
}
} else {
2024-06-17 18:12:38 +02:00
for _ , bwc := range ul . bandwidth {
latestJe , err := a . isBandwidthClassLimitedForAccount ( * env . AccountId , bwc , trx )
2024-06-04 22:50:08 +02:00
if err != nil {
return false , err
}
2024-06-17 18:12:38 +02:00
if latestJe != nil {
2024-06-04 22:50:08 +02:00
return false , nil
}
}
}
2024-06-17 18:12:38 +02:00
rc := ul . resource
if scopeRc , found := ul . scopes [ sdk . BackendMode ( shr . BackendMode ) ] ; found {
rc = scopeRc
}
if rc . GetShareFrontends ( ) > store . Unlimited {
2024-06-17 19:16:07 +02:00
fes , err := a . str . FindFrontendsForPrivateShare ( shr . Id , trx )
if err != nil {
return false , err
}
if len ( fes ) + 1 > rc . GetShareFrontends ( ) {
2024-06-25 20:09:50 +02:00
logrus . Infof ( "account '#%d' over frontends per share limit '%d'" , * env . AccountId , rc . GetShareFrontends ( ) )
2024-06-17 19:16:07 +02:00
return false , nil
}
2024-06-17 18:12:38 +02:00
}
2024-06-04 22:50:08 +02:00
} else {
return false , nil
2023-06-06 17:29:22 +02:00
}
}
2023-06-06 16:54:57 +02:00
return true , nil
}
2023-03-16 20:05:39 +01:00
func ( a * Agent ) Handle ( u * metrics . Usage ) error {
2023-03-21 18:05:22 +01:00
logrus . Debugf ( "handling: %v" , u )
a . queue <- u
2023-03-16 20:05:39 +01:00
return nil
}
2023-03-17 18:13:33 +01:00
func ( a * Agent ) run ( ) {
logrus . Info ( "started" )
defer logrus . Info ( "stopped" )
2023-03-29 23:03:42 +02:00
lastCycle := time . Now ( )
2023-03-17 18:13:33 +01:00
mainLoop :
for {
select {
2023-03-21 18:05:22 +01:00
case usage := <- a . queue :
2023-06-16 19:18:46 +02:00
if usage . ShareToken != "" {
if err := a . enforce ( usage ) ; err != nil {
logrus . Errorf ( "error running enforcement: %v" , err )
}
if time . Since ( lastCycle ) > a . cfg . Cycle {
if err := a . relax ( ) ; err != nil {
logrus . Errorf ( "error running relax cycle: %v" , err )
}
lastCycle = time . Now ( )
2023-03-29 23:03:42 +02:00
}
2023-06-16 19:18:46 +02:00
} else {
2023-06-16 19:28:00 +02:00
logrus . Warnf ( "not enforcing for usage with no share token: %v" , usage . String ( ) )
2023-03-29 23:03:42 +02:00
}
2023-03-21 18:05:22 +01:00
2023-03-17 18:13:33 +01:00
case <- time . After ( a . cfg . Cycle ) :
2023-03-23 20:13:59 +01:00
if err := a . relax ( ) ; err != nil {
logrus . Errorf ( "error running relax cycle: %v" , err )
}
2023-03-29 23:03:42 +02:00
lastCycle = time . Now ( )
2023-03-17 18:13:33 +01:00
case <- a . close :
close ( a . join )
break mainLoop
}
}
}
2023-03-21 18:05:22 +01:00
2023-03-21 19:06:23 +01:00
func ( a * Agent ) enforce ( u * metrics . Usage ) error {
trx , err := a . str . Begin ( )
if err != nil {
return errors . Wrap ( err , "error starting transaction" )
}
defer func ( ) { _ = trx . Rollback ( ) } ( )
2023-06-07 17:00:42 +02:00
acct , err := a . str . GetAccount ( int ( u . AccountId ) , trx )
if err != nil {
return err
}
if acct . Limitless {
return nil
}
2024-06-05 23:03:24 +02:00
shr , err := a . str . FindShareWithTokenEvenIfDeleted ( u . ShareToken , trx )
if err != nil {
return err
}
2024-06-04 20:06:44 +02:00
2024-06-05 22:54:05 +02:00
ul , err := a . getUserLimits ( int ( u . AccountId ) , trx )
2024-06-04 20:06:44 +02:00
if err != nil {
return err
}
2024-06-05 22:54:05 +02:00
2024-06-11 18:00:12 +02:00
exceededBwc , rxBytes , txBytes , err := a . anyBandwidthLimitExceeded ( acct , u , ul . toBandwidthArray ( sdk . BackendMode ( shr . BackendMode ) ) )
2024-06-04 20:06:44 +02:00
if err != nil {
return errors . Wrap ( err , "error checking limit classes" )
}
2024-06-07 17:38:49 +02:00
if exceededBwc != nil {
latestJe , err := a . isBandwidthClassLimitedForAccount ( int ( u . AccountId ) , exceededBwc , trx )
if err != nil {
return err
2024-06-04 20:06:44 +02:00
}
2024-06-07 17:38:49 +02:00
if latestJe == nil {
2024-06-04 20:06:44 +02:00
je := & store . BandwidthLimitJournalEntry {
AccountId : int ( u . AccountId ) ,
RxBytes : rxBytes ,
TxBytes : txBytes ,
2024-06-07 17:38:49 +02:00
Action : exceededBwc . GetLimitAction ( ) ,
2023-03-22 19:10:07 +01:00
}
2024-06-07 17:38:49 +02:00
if ! exceededBwc . IsGlobal ( ) {
lcId := exceededBwc . GetLimitClassId ( )
2024-06-04 20:06:44 +02:00
je . LimitClassId = & lcId
}
2024-06-06 03:11:23 +02:00
if _ , err := a . str . CreateBandwidthLimitJournalEntry ( je , trx ) ; err != nil {
2024-06-04 20:06:44 +02:00
return err
}
acct , err := a . str . GetAccount ( int ( u . AccountId ) , trx )
if err != nil {
return err
}
2024-06-07 17:38:49 +02:00
switch exceededBwc . GetLimitAction ( ) {
2024-06-04 20:06:44 +02:00
case store . LimitLimitAction :
for _ , limitAction := range a . limitActions {
2024-06-07 17:38:49 +02:00
if err := limitAction . HandleAccount ( acct , rxBytes , txBytes , exceededBwc , ul , trx ) ; err != nil {
2024-06-04 20:06:44 +02:00
return errors . Wrapf ( err , "%v" , reflect . TypeOf ( limitAction ) . String ( ) )
2023-03-27 19:00:05 +02:00
}
}
2024-06-04 20:06:44 +02:00
case store . WarningLimitAction :
for _ , warningAction := range a . warningActions {
2024-06-07 17:38:49 +02:00
if err := warningAction . HandleAccount ( acct , rxBytes , txBytes , exceededBwc , ul , trx ) ; err != nil {
2024-06-04 20:06:44 +02:00
return errors . Wrapf ( err , "%v" , reflect . TypeOf ( warningAction ) . String ( ) )
}
2023-03-22 19:10:07 +01:00
}
}
2024-06-04 20:06:44 +02:00
if err := trx . Commit ( ) ; err != nil {
return err
}
} else {
2024-06-07 17:38:49 +02:00
logrus . Debugf ( "limit '%v' already applied for '%v' (at: %v)" , exceededBwc , acct . Email , latestJe . CreatedAt )
2023-03-21 19:06:23 +01:00
}
}
return nil
}
2023-03-23 20:13:59 +01:00
func ( a * Agent ) relax ( ) error {
2023-03-28 21:19:01 +02:00
logrus . Debug ( "relaxing" )
2023-03-23 20:13:59 +01:00
trx , err := a . str . Begin ( )
2023-03-21 19:06:23 +01:00
if err != nil {
2023-03-23 20:13:59 +01:00
return errors . Wrap ( err , "error starting transaction" )
}
defer func ( ) { _ = trx . Rollback ( ) } ( )
commit := false
2024-06-04 20:06:44 +02:00
if bwjes , err := a . str . FindAllBandwidthLimitJournal ( trx ) ; err == nil {
accounts := make ( map [ int ] * store . Account )
2024-06-06 19:49:36 +02:00
uls := make ( map [ int ] * userLimits )
2024-06-12 20:16:25 +02:00
accountPeriods := make ( map [ int ] map [ int ] * periodBwValues )
2024-06-04 20:06:44 +02:00
for _ , bwje := range bwjes {
if _ , found := accounts [ bwje . AccountId ] ; ! found {
if acct , err := a . str . GetAccount ( bwje . AccountId , trx ) ; err == nil {
accounts [ bwje . AccountId ] = acct
2024-06-06 19:49:36 +02:00
ul , err := a . getUserLimits ( acct . Id , trx )
if err != nil {
return errors . Wrapf ( err , "error getting user limits for '%v'" , acct . Email )
}
uls [ bwje . AccountId ] = ul
2024-06-12 20:16:25 +02:00
accountPeriods [ bwje . AccountId ] = make ( map [ int ] * periodBwValues )
2024-06-04 20:06:44 +02:00
} else {
return err
}
}
var bwc store . BandwidthClass
2024-06-05 17:45:14 +02:00
if bwje . LimitClassId == nil {
2024-06-04 20:06:44 +02:00
globalBwcs := newConfigBandwidthClasses ( a . cfg . Bandwidth )
if bwje . Action == store . WarningLimitAction {
bwc = globalBwcs [ 0 ]
} else {
bwc = globalBwcs [ 1 ]
}
} else {
lc , err := a . str . GetLimitClass ( * bwje . LimitClassId , trx )
if err != nil {
return err
}
bwc = lc
}
2024-06-12 20:16:25 +02:00
if periods , accountFound := accountPeriods [ bwje . AccountId ] ; accountFound {
if _ , periodFound := periods [ bwc . GetPeriodMinutes ( ) ] ; ! periodFound {
rx , tx , err := a . ifx . totalRxTxForAccount ( int64 ( bwje . AccountId ) , time . Duration ( bwc . GetPeriodMinutes ( ) ) * time . Minute )
if err != nil {
return err
}
periods [ bwc . GetPeriodMinutes ( ) ] = & periodBwValues { rx : rx , tx : tx }
accountPeriods [ bwje . AccountId ] = periods
2024-06-04 20:06:44 +02:00
}
2024-06-12 20:16:25 +02:00
} else {
return errors . New ( "accountPeriods corrupted" )
2024-06-04 20:06:44 +02:00
}
2024-06-12 20:16:25 +02:00
used := accountPeriods [ bwje . AccountId ] [ bwc . GetPeriodMinutes ( ) ]
2024-06-07 17:38:49 +02:00
if ! a . transferBytesExceeded ( used . rx , used . tx , bwc ) {
2024-06-04 20:06:44 +02:00
if bwc . GetLimitAction ( ) == store . LimitLimitAction {
2024-06-05 17:45:14 +02:00
logrus . Infof ( "relaxing limit '%v' for '%v'" , bwc . String ( ) , accounts [ bwje . AccountId ] . Email )
2024-06-04 20:06:44 +02:00
for _ , action := range a . relaxActions {
2024-06-06 19:49:36 +02:00
if err := action . HandleAccount ( accounts [ bwje . AccountId ] , used . rx , used . tx , bwc , uls [ bwje . AccountId ] , trx ) ; err != nil {
2024-06-04 20:06:44 +02:00
return errors . Wrapf ( err , "%v" , reflect . TypeOf ( action ) . String ( ) )
2023-03-23 20:13:59 +01:00
}
}
2024-06-04 20:06:44 +02:00
} else {
2024-06-05 17:45:14 +02:00
logrus . Infof ( "relaxing warning '%v' for '%v'" , bwc . String ( ) , accounts [ bwje . AccountId ] . Email )
2024-06-04 20:06:44 +02:00
}
2024-06-05 17:45:14 +02:00
if bwc . IsGlobal ( ) {
if err := a . str . DeleteBandwidthLimitJournalEntryForGlobal ( bwje . AccountId , trx ) ; err == nil {
commit = true
} else {
logrus . Errorf ( "error deleting global bandwidth limit journal entry for '%v': %v" , accounts [ bwje . AccountId ] . Email , err )
}
2024-06-04 20:06:44 +02:00
} else {
2024-06-05 17:45:14 +02:00
if err := a . str . DeleteBandwidthLimitJournalEntryForLimitClass ( bwje . AccountId , * bwje . LimitClassId , trx ) ; err == nil {
commit = true
} else {
logrus . Errorf ( "error deleting bandwidth limit journal entry for '%v': %v" , accounts [ bwje . AccountId ] . Email , err )
}
2023-03-23 20:13:59 +01:00
}
} else {
2024-06-11 18:00:12 +02:00
logrus . Infof ( "'%v' still over limit: '%v' with rx: %v, tx: %v, total: %v" , accounts [ bwje . AccountId ] . Email , bwc , util . BytesToSize ( used . rx ) , util . BytesToSize ( used . tx ) , util . BytesToSize ( used . rx + used . tx ) )
2023-03-23 20:13:59 +01:00
}
}
} else {
return err
2023-03-21 19:06:23 +01:00
}
2023-03-23 20:13:59 +01:00
if commit {
if err := trx . Commit ( ) ; err != nil {
return err
}
}
return nil
}
2024-06-07 17:38:49 +02:00
func ( a * Agent ) isBandwidthClassLimitedForAccount ( acctId int , bwc store . BandwidthClass , trx * sqlx . Tx ) ( * store . BandwidthLimitJournalEntry , error ) {
if bwc . IsGlobal ( ) {
if empty , err := a . str . IsBandwidthLimitJournalEmptyForGlobal ( acctId , trx ) ; err == nil && ! empty {
je , err := a . str . FindLatestBandwidthLimitJournalForGlobal ( acctId , trx )
if err != nil {
return nil , err
}
2024-06-27 19:09:28 +02:00
if je . Action == bwc . GetLimitAction ( ) {
2024-06-11 18:00:12 +02:00
logrus . Debugf ( "account '#%d' over bandwidth for global bandwidth class '%v'" , acctId , bwc )
2024-06-07 17:38:49 +02:00
return je , nil
}
} else if err != nil {
return nil , err
}
} else {
if empty , err := a . str . IsBandwidthLimitJournalEmptyForLimitClass ( acctId , bwc . GetLimitClassId ( ) , trx ) ; err == nil && ! empty {
je , err := a . str . FindLatestBandwidthLimitJournalForLimitClass ( acctId , bwc . GetLimitClassId ( ) , trx )
if err != nil {
return nil , err
}
2024-06-27 19:09:28 +02:00
if je . Action == bwc . GetLimitAction ( ) {
2024-06-11 18:00:12 +02:00
logrus . Debugf ( "account '#%d' over bandwidth for limit class '%v'" , acctId , bwc )
2024-06-07 17:38:49 +02:00
return je , nil
}
} else if err != nil {
return nil , err
}
}
return nil , nil
}
2024-06-11 18:00:12 +02:00
func ( a * Agent ) anyBandwidthLimitExceeded ( acct * store . Account , u * metrics . Usage , bwcs [ ] store . BandwidthClass ) ( store . BandwidthClass , int64 , int64 , error ) {
2024-06-12 20:16:25 +02:00
periodBw := make ( map [ int ] periodBwValues )
2024-06-04 20:06:44 +02:00
2024-06-05 22:54:05 +02:00
var selectedLc store . BandwidthClass
var rxBytes int64
var txBytes int64
2024-06-04 20:06:44 +02:00
2024-06-05 22:54:05 +02:00
for _ , bwc := range bwcs {
2024-06-04 20:06:44 +02:00
if _ , found := periodBw [ bwc . GetPeriodMinutes ( ) ] ; ! found {
rx , tx , err := a . ifx . totalRxTxForAccount ( u . AccountId , time . Minute * time . Duration ( bwc . GetPeriodMinutes ( ) ) )
if err != nil {
2024-06-11 18:00:12 +02:00
return nil , 0 , 0 , errors . Wrapf ( err , "error getting rx/tx for account '%v'" , acct . Email )
2024-06-04 20:06:44 +02:00
}
2024-06-12 20:16:25 +02:00
periodBw [ bwc . GetPeriodMinutes ( ) ] = periodBwValues { rx : rx , tx : tx }
2024-06-04 20:06:44 +02:00
}
2024-06-05 22:54:05 +02:00
period := periodBw [ bwc . GetPeriodMinutes ( ) ]
2024-06-04 20:06:44 +02:00
2024-06-07 17:38:49 +02:00
if a . transferBytesExceeded ( period . rx , period . tx , bwc ) {
2024-06-05 22:54:05 +02:00
selectedLc = bwc
rxBytes = period . rx
txBytes = period . tx
} else {
2024-06-11 18:00:12 +02:00
logrus . Debugf ( "'%v' limit ok '%v' with rx: %v, tx: %v, total: %v" , acct . Email , bwc , util . BytesToSize ( period . rx ) , util . BytesToSize ( period . tx ) , util . BytesToSize ( period . rx + period . tx ) )
2024-06-04 20:06:44 +02:00
}
2023-03-21 18:05:22 +01:00
}
2023-03-21 19:06:23 +01:00
2024-06-05 22:54:05 +02:00
if selectedLc != nil {
2024-06-11 18:00:12 +02:00
logrus . Infof ( "'%v' exceeded limit '%v' with rx: %v, tx: %v, total: %v" , acct . Email , selectedLc , util . BytesToSize ( rxBytes ) , util . BytesToSize ( txBytes ) , util . BytesToSize ( rxBytes + txBytes ) )
2024-06-05 22:54:05 +02:00
}
2024-06-04 20:06:44 +02:00
return selectedLc , rxBytes , txBytes , nil
2023-03-21 19:06:23 +01:00
}
2024-06-07 17:38:49 +02:00
func ( a * Agent ) transferBytesExceeded ( rx , tx int64 , bwc store . BandwidthClass ) bool {
2024-06-05 21:20:33 +02:00
if bwc . GetTxBytes ( ) != store . Unlimited && tx >= bwc . GetTxBytes ( ) {
2024-06-04 20:06:44 +02:00
return true
2023-03-21 19:06:23 +01:00
}
2024-06-05 21:20:33 +02:00
if bwc . GetRxBytes ( ) != store . Unlimited && rx >= bwc . GetRxBytes ( ) {
2024-06-04 20:06:44 +02:00
return true
2023-03-21 19:06:23 +01:00
}
2024-06-05 21:20:33 +02:00
if bwc . GetTotalBytes ( ) != store . Unlimited && tx + rx >= bwc . GetTotalBytes ( ) {
2024-06-04 20:06:44 +02:00
return true
2023-03-21 19:06:23 +01:00
}
2024-06-04 20:06:44 +02:00
return false
2023-03-21 19:06:23 +01:00
}
2024-06-12 20:16:25 +02:00
type periodBwValues struct {
rx int64
tx int64
}