New service ChargerS with initial config and TP structure

This commit is contained in:
DanB
2018-07-09 19:11:24 +02:00
parent 44101eb421
commit 2570ab7b3a
12 changed files with 223 additions and 18 deletions

View File

@@ -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
View 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
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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 {

View File

@@ -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{},

View File

@@ -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,

View File

@@ -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

View File

@@ -0,0 +1 @@
#Tenant,ID,FilterIDs,ActivationInterval,RunID,AttributeIDs,Weight
1 #Tenant ID FilterIDs ActivationInterval RunID AttributeIDs Weight

54
engine/chargers.go Normal file
View 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
}

View File

@@ -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
}

View File

@@ -655,6 +655,7 @@ const (
APIKey = "APIKey"
APIMethods = "APIMethods"
NestingSep = "."
ChargerS = "ChargerS"
)
// MetaFilterIndexesAPIs