mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
New service ChargerS with initial config and TP structure
This commit is contained in:
@@ -57,14 +57,10 @@ func TestHAitInitCfg(t *testing.T) {
|
||||
}
|
||||
|
||||
// Remove data in both rating and accounting db
|
||||
func TestHAitResetDataDb(t *testing.T) {
|
||||
func TestHAitResetDB(t *testing.T) {
|
||||
if err := engine.InitDataDb(haCfg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Wipe out the cdr database
|
||||
func TestHAitResetStorDb(t *testing.T) {
|
||||
if err := engine.InitStorDb(haCfg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
58
config/chargerscfg.go
Normal file
58
config/chargerscfg.go
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package config
|
||||
|
||||
// SupplierSCfg is the configuration of supplier service
|
||||
type ChargerSCfg struct {
|
||||
Enabled bool
|
||||
AttributeSConns []*HaPoolConfig
|
||||
StringIndexedFields *[]string
|
||||
PrefixIndexedFields *[]string
|
||||
}
|
||||
|
||||
func (cS *ChargerSCfg) loadFromJsonCfg(jsnCfg *ChargerSJsonCfg) (err error) {
|
||||
if jsnCfg == nil {
|
||||
return
|
||||
}
|
||||
if jsnCfg.Enabled != nil {
|
||||
cS.Enabled = *jsnCfg.Enabled
|
||||
}
|
||||
if jsnCfg.Attributes_conns != nil {
|
||||
cS.AttributeSConns = make([]*HaPoolConfig, len(*jsnCfg.Attributes_conns))
|
||||
for idx, jsnHaCfg := range *jsnCfg.Attributes_conns {
|
||||
cS.AttributeSConns[idx] = NewDfltHaPoolConfig()
|
||||
cS.AttributeSConns[idx].loadFromJsonCfg(jsnHaCfg)
|
||||
}
|
||||
}
|
||||
if jsnCfg.String_indexed_fields != nil {
|
||||
sif := make([]string, len(*jsnCfg.String_indexed_fields))
|
||||
for i, fID := range *jsnCfg.String_indexed_fields {
|
||||
sif[i] = fID
|
||||
}
|
||||
cS.StringIndexedFields = &sif
|
||||
}
|
||||
if jsnCfg.Prefix_indexed_fields != nil {
|
||||
pif := make([]string, len(*jsnCfg.Prefix_indexed_fields))
|
||||
for i, fID := range *jsnCfg.Prefix_indexed_fields {
|
||||
pif[i] = fID
|
||||
}
|
||||
cS.PrefixIndexedFields = &pif
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -341,19 +341,20 @@ type CGRConfig struct {
|
||||
CdreProfiles map[string]*CdreConfig
|
||||
CdrcProfiles map[string][]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath][]{Configs}
|
||||
sessionSCfg *SessionSCfg
|
||||
fsAgentCfg *FsAgentConfig // FreeSWITCHAgent configuration
|
||||
kamAgentCfg *KamAgentCfg // KamailioAgent Configuration
|
||||
SmOsipsConfig *SmOsipsConfig // SMOpenSIPS Configuration
|
||||
asteriskAgentCfg *AsteriskAgentCfg // SMAsterisk Configuration
|
||||
diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
|
||||
radiusAgentCfg *RadiusAgentCfg // RadiusAgent configuration
|
||||
httpAgentCfg []*HttpAgentCfg // HttpAgent configuration
|
||||
filterSCfg *FilterSCfg // FilterS configuration
|
||||
PubSubServerEnabled bool // Starts PubSub as server: <true|false>.
|
||||
AliasesServerEnabled bool // Starts PubSub as server: <true|false>.
|
||||
UserServerEnabled bool // Starts User as server: <true|false>
|
||||
UserServerIndexes []string // List of user profile field indexes
|
||||
attributeSCfg *AttributeSCfg // Attribute service configuration
|
||||
fsAgentCfg *FsAgentConfig // FreeSWITCHAgent configuration
|
||||
kamAgentCfg *KamAgentCfg // KamailioAgent Configuration
|
||||
SmOsipsConfig *SmOsipsConfig // SMOpenSIPS Configuration
|
||||
asteriskAgentCfg *AsteriskAgentCfg // SMAsterisk Configuration
|
||||
diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
|
||||
radiusAgentCfg *RadiusAgentCfg // RadiusAgent configuration
|
||||
httpAgentCfg []*HttpAgentCfg // HttpAgent configuration
|
||||
filterSCfg *FilterSCfg // FilterS configuration
|
||||
PubSubServerEnabled bool // Starts PubSub as server: <true|false>.
|
||||
AliasesServerEnabled bool // Starts PubSub as server: <true|false>.
|
||||
UserServerEnabled bool // Starts User as server: <true|false>
|
||||
UserServerIndexes []string // List of user profile field indexes
|
||||
attributeSCfg *AttributeSCfg // Attribute service configuration
|
||||
chargerSCfg *ChargerSCfg
|
||||
resourceSCfg *ResourceSConfig // Configuration for resource limiter
|
||||
statsCfg *StatSCfg // Configuration for StatS
|
||||
thresholdSCfg *ThresholdSCfg // configuration for ThresholdS
|
||||
@@ -646,6 +647,14 @@ func (self *CGRConfig) checkConfigSanity() error {
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.chargerSCfg != nil && self.chargerSCfg.Enabled {
|
||||
for _, connCfg := range self.chargerSCfg.AttributeSConns {
|
||||
if connCfg.Address == utils.MetaInternal &&
|
||||
(self.attributeSCfg == nil || !self.attributeSCfg.Enabled) {
|
||||
return errors.New("AttributeS not enabled but requested by ChargerS component.")
|
||||
}
|
||||
}
|
||||
}
|
||||
// ResourceLimiter checks
|
||||
if self.resourceSCfg != nil && self.resourceSCfg.Enabled {
|
||||
for _, connCfg := range self.resourceSCfg.ThresholdSConns {
|
||||
@@ -818,6 +827,11 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
jsnChargerSCfg, err := jsnCfg.ChargerServJsonCfg()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsnRLSCfg, err := jsnCfg.ResourceSJsonCfg()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1376,6 +1390,15 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if jsnChargerSCfg != nil {
|
||||
if self.chargerSCfg == nil {
|
||||
self.chargerSCfg = new(ChargerSCfg)
|
||||
}
|
||||
if self.chargerSCfg.loadFromJsonCfg(jsnChargerSCfg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if jsnRLSCfg != nil {
|
||||
if self.resourceSCfg == nil {
|
||||
self.resourceSCfg = new(ResourceSConfig)
|
||||
@@ -1496,6 +1519,10 @@ func (cfg *CGRConfig) AttributeSCfg() *AttributeSCfg {
|
||||
return cfg.attributeSCfg
|
||||
}
|
||||
|
||||
func (cfg *CGRConfig) ChargerSCfg() *ChargerSCfg {
|
||||
return cfg.chargerSCfg
|
||||
}
|
||||
|
||||
// ToDo: fix locking here
|
||||
func (self *CGRConfig) ResourceSCfg() *ResourceSConfig {
|
||||
return self.resourceSCfg
|
||||
|
||||
@@ -429,6 +429,14 @@ const CGRATES_CFG_JSON = `
|
||||
},
|
||||
|
||||
|
||||
"chargers": { // Charger service
|
||||
"enabled": false, // starts charger service: <true|false>.
|
||||
"attributes_conns": [], // address where to reach the AttributeS <""|127.0.0.1:2013>
|
||||
//"string_indexed_fields": [], // query indexes based on these fields for faster processing
|
||||
"prefix_indexed_fields": [], // query indexes based on these fields for faster processing
|
||||
},
|
||||
|
||||
|
||||
"resources": { // Resource service (*new)
|
||||
"enabled": false, // starts ResourceLimiter service: <true|false>.
|
||||
"store_interval": "", // dump cache regularly to dataDB, 0 - dump at start/shutdown: <""|$dur>
|
||||
|
||||
@@ -67,6 +67,7 @@ const (
|
||||
DispatcherSJson = "dispatcher"
|
||||
CgrLoaderCfgJson = "loader"
|
||||
CgrMigratorCfgJson = "migrator"
|
||||
ChargerSCfgJson = "chargers"
|
||||
)
|
||||
|
||||
// Loads the json config out of io.Reader, eg other sources than file, maybe over http
|
||||
@@ -368,6 +369,18 @@ func (cgrJsn CgrJsonCfg) AttributeServJsonCfg() (*AttributeSJsonCfg, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (cgrJsn CgrJsonCfg) ChargerServJsonCfg() (*ChargerSJsonCfg, error) {
|
||||
rawCfg, hasKey := cgrJsn[ChargerSCfgJson]
|
||||
if !hasKey {
|
||||
return nil, nil
|
||||
}
|
||||
cfg := new(ChargerSJsonCfg)
|
||||
if err := json.Unmarshal(*rawCfg, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (self CgrJsonCfg) ResourceSJsonCfg() (*ResourceSJsonCfg, error) {
|
||||
rawCfg, hasKey := self[RESOURCES_JSON]
|
||||
if !hasKey {
|
||||
|
||||
@@ -705,6 +705,20 @@ func TestDfAttributeServJsonCfg(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDfChargerServJsonCfg(t *testing.T) {
|
||||
eCfg := &ChargerSJsonCfg{
|
||||
Enabled: utils.BoolPointer(false),
|
||||
Attributes_conns: &[]*HaPoolJsonCfg{},
|
||||
String_indexed_fields: nil,
|
||||
Prefix_indexed_fields: &[]string{},
|
||||
}
|
||||
if cfg, err := dfCgrJsonCfg.ChargerServJsonCfg(); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCfg, cfg) {
|
||||
t.Error("Received: ", cfg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDfFilterSJsonCfg(t *testing.T) {
|
||||
eCfg := &FilterSJsonCfg{
|
||||
Stats_conns: &[]*HaPoolJsonCfg{},
|
||||
|
||||
@@ -801,6 +801,18 @@ func TestCgrCfgJSONDefaultSAttributeSCfg(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCgrCfgJSONDefaultSChargerSCfg(t *testing.T) {
|
||||
eChargerSCfg := &ChargerSCfg{
|
||||
Enabled: false,
|
||||
AttributeSConns: []*HaPoolConfig{},
|
||||
StringIndexedFields: nil,
|
||||
PrefixIndexedFields: &[]string{},
|
||||
}
|
||||
if !reflect.DeepEqual(eChargerSCfg, cgrCfg.chargerSCfg) {
|
||||
t.Errorf("received: %+v, expecting: %+v", eChargerSCfg, cgrCfg.chargerSCfg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCgrCfgJSONDefaultsResLimCfg(t *testing.T) {
|
||||
eResLiCfg := &ResourceSConfig{
|
||||
Enabled: false,
|
||||
|
||||
@@ -429,6 +429,14 @@ type AttributeSJsonCfg struct {
|
||||
Prefix_indexed_fields *[]string
|
||||
}
|
||||
|
||||
// ChargerSJsonCfg service config section
|
||||
type ChargerSJsonCfg struct {
|
||||
Enabled *bool
|
||||
Attributes_conns *[]*HaPoolJsonCfg
|
||||
String_indexed_fields *[]string
|
||||
Prefix_indexed_fields *[]string
|
||||
}
|
||||
|
||||
// ResourceLimiter service config section
|
||||
type ResourceSJsonCfg struct {
|
||||
Enabled *bool
|
||||
|
||||
1
data/tariffplans/tutorial/Chargers.csv
Normal file
1
data/tariffplans/tutorial/Chargers.csv
Normal file
@@ -0,0 +1 @@
|
||||
#Tenant,ID,FilterIDs,ActivationInterval,RunID,AttributeIDs,Weight
|
||||
|
54
engine/chargers.go
Normal file
54
engine/chargers.go
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func NewChargerService(dm *DataManager, filterS *FilterS,
|
||||
strgIdxFlds, prfxIdxFlds *[]string) (*ChargerService, error) {
|
||||
return &ChargerService{dm: dm, filterS: filterS,
|
||||
strgIdxFlds: strgIdxFlds,
|
||||
prfxIdxFlds: prfxIdxFlds}, nil
|
||||
}
|
||||
|
||||
type ChargerService struct {
|
||||
dm *DataManager
|
||||
filterS *FilterS
|
||||
strgIdxFlds *[]string
|
||||
prfxIdxFlds *[]string
|
||||
}
|
||||
|
||||
// ListenAndServe will initialize the service
|
||||
func (cS *ChargerService) ListenAndServe(exitChan chan bool) (err error) {
|
||||
utils.Logger.Info(fmt.Sprintf("Starting %s", utils.ChargerS))
|
||||
e := <-exitChan
|
||||
exitChan <- e
|
||||
return
|
||||
}
|
||||
|
||||
// Shutdown is called to shutdown the service
|
||||
func (cS *ChargerService) Shutdown() (err error) {
|
||||
utils.Logger.Info(fmt.Sprintf("<%s> shutdown initialized", utils.ChargerS))
|
||||
utils.Logger.Info(fmt.Sprintf("<%s> shutdown complete", utils.ChargerS))
|
||||
return
|
||||
}
|
||||
@@ -558,3 +558,16 @@ type TPAttribute struct {
|
||||
Weight float64 `index:"9" re:"\d+\.?\d*"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type TPCharger struct {
|
||||
PK uint `gorm:"primary_key"`
|
||||
Tpid string
|
||||
Tenant string `index:"0" re:""`
|
||||
ID string `index:"1" re:""`
|
||||
FilterIDs string `index:"2" re:""`
|
||||
ActivationInterval string `index:"3" re:""`
|
||||
RunID string `index:"4" re:""`
|
||||
AttributeIDs string `index:"5" re:""`
|
||||
Weight float64 `index:"6" re:"\d+\.?\d*"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
@@ -655,6 +655,7 @@ const (
|
||||
APIKey = "APIKey"
|
||||
APIMethods = "APIMethods"
|
||||
NestingSep = "."
|
||||
ChargerS = "ChargerS"
|
||||
)
|
||||
|
||||
// MetaFilterIndexesAPIs
|
||||
|
||||
Reference in New Issue
Block a user