diff --git a/config/config.go b/config/config.go index fab72222e..7b12732db 100644 --- a/config/config.go +++ b/config/config.go @@ -61,6 +61,7 @@ func SetCgrConfig(cfg *CGRConfig) { func NewDefaultCGRConfig() (*CGRConfig, error) { cfg := new(CGRConfig) cfg.DataFolderPath = "/usr/share/cgrates/" + cfg.SmGenericConfig = new(SmGenericConfig) cfg.SmFsConfig = new(SmFsConfig) cfg.SmKamConfig = new(SmKamConfig) cfg.SmOsipsConfig = new(SmOsipsConfig) @@ -224,24 +225,25 @@ type CGRConfig struct { CDRStatsSaveInterval time.Duration // Save interval duration CdreProfiles map[string]*CdreConfig CdrcProfiles map[string]map[string]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath]map[instanceName]{Configs} - SmFsConfig *SmFsConfig // SM-FreeSWITCH configuration - SmKamConfig *SmKamConfig // SM-Kamailio Configuration - SmOsipsConfig *SmOsipsConfig // SM-OpenSIPS Configuration - HistoryServer string // Address where to reach the master history server: - HistoryServerEnabled bool // Starts History as server: . - HistoryDir string // Location on disk where to store history files. - HistorySaveInterval time.Duration // The timout duration between pubsub writes - PubSubServerEnabled bool // Starts PubSub as server: . - AliasesServerEnabled bool // Starts PubSub as server: . - UserServerEnabled bool // Starts User as server: - UserServerIndexes []string // List of user profile field indexes - MailerServer string // The server to use when sending emails out - MailerAuthUser string // Authenticate to email server using this user - MailerAuthPass string // Authenticate to email server with this password - MailerFromAddr string // From address used when sending emails out - DataFolderPath string // Path towards data folder, for tests internal usage, not loading out of .json options - sureTaxCfg *SureTaxCfg // Load here SureTax configuration, as pointer so we can have runtime reloads in the future - ConfigReloads map[string]chan struct{} // Signals to specific entities that a config reload should occur + SmGenericConfig *SmGenericConfig + SmFsConfig *SmFsConfig // SM-FreeSWITCH configuration + SmKamConfig *SmKamConfig // SM-Kamailio Configuration + SmOsipsConfig *SmOsipsConfig // SM-OpenSIPS Configuration + HistoryServer string // Address where to reach the master history server: + HistoryServerEnabled bool // Starts History as server: . + HistoryDir string // Location on disk where to store history files. + HistorySaveInterval time.Duration // The timout duration between pubsub writes + PubSubServerEnabled bool // Starts PubSub as server: . + AliasesServerEnabled bool // Starts PubSub as server: . + UserServerEnabled bool // Starts User as server: + UserServerIndexes []string // List of user profile field indexes + MailerServer string // The server to use when sending emails out + MailerAuthUser string // Authenticate to email server using this user + MailerAuthPass string // Authenticate to email server with this password + MailerFromAddr string // From address used when sending emails out + DataFolderPath string // Path towards data folder, for tests internal usage, not loading out of .json options + sureTaxCfg *SureTaxCfg // Load here SureTax configuration, as pointer so we can have runtime reloads in the future + ConfigReloads map[string]chan struct{} // Signals to specific entities that a config reload should occur // Cache defaults loaded from json and needing clones dfltCdreProfile *CdreConfig // Default cdreConfig profile dfltCdrcProfile *CdrcConfig // Default cdrcConfig profile @@ -312,6 +314,21 @@ func (self *CGRConfig) checkConfigSanity() error { } } } + // SM-Generic checks + if self.SmGenericConfig.Enabled { + if len(self.SmGenericConfig.HaRater) == 0 { + return errors.New("Rater definition is mandatory!") + } + if len(self.SmGenericConfig.HaCdrs) == 0 { + return errors.New("Cdrs definition is mandatory!") + } + if self.SmGenericConfig.HaRater[0].Server == utils.INTERNAL && !self.RaterEnabled { + return errors.New("Rater not enabled but requested by SM-Generic component.") + } + if self.SmGenericConfig.HaCdrs[0].Server == utils.INTERNAL && !self.CDRSEnabled { + return errors.New("CDRS not enabled but referenced by SM-Generic component") + } + } // SM-FreeSWITCH checks if self.SmFsConfig.Enabled { if len(self.SmFsConfig.HaRater) == 0 { @@ -424,6 +441,11 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error { return err } + jsnSmGenericCfg, err := jsnCfg.SmGenericJsonCfg() + if err != nil { + return err + } + jsnSmFsCfg, err := jsnCfg.SmFsJsonCfg() if err != nil { return err @@ -737,6 +759,11 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error { } } + if jsnSmGenericCfg != nil { + if err := self.SmGenericConfig.loadFromJsonCfg(jsnSmGenericCfg); err != nil { + return err + } + } if jsnSmFsCfg != nil { if err := self.SmFsConfig.loadFromJsonCfg(jsnSmFsCfg); err != nil { return err diff --git a/config/config_defaults.go b/config/config_defaults.go index 0a8b4754c..ce43d451e 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -197,6 +197,15 @@ const CGRATES_CFG_JSON = ` } }, +"sm_generic": { + "enabled": false, // starts SessionManager service: + "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> + "cdrs": "internal", // address where to reach CDR Server <""|internal|x.y.z.y:1234> + "debit_interval": "10s", // interval to perform debits on. + "min_call_duration": "0s", // only authorize calls with allowed duration higher than this + "max_call_duration": "3h", // maximum call duration a prepaid call can last +}, + "sm_freeswitch": { "enabled": false, // starts SessionManager service: diff --git a/config/config_json.go b/config/config_json.go index 33d7663a6..17616f653 100644 --- a/config/config_json.go +++ b/config/config_json.go @@ -40,6 +40,7 @@ const ( CDRSTATS_JSN = "cdrstats" CDRE_JSN = "cdre" CDRC_JSN = "cdrc" + SMGENERIC_JSON = "sm_generic" SMFS_JSN = "sm_freeswitch" SMKAM_JSN = "sm_kamailio" SMOSIPS_JSN = "sm_opensips" @@ -198,6 +199,18 @@ func (self CgrJsonCfg) CdrcJsonCfg() (map[string]*CdrcJsonCfg, error) { return cfg, nil } +func (self CgrJsonCfg) SmGenericJsonCfg() (*SmGenericJsonCfg, error) { + rawCfg, hasKey := self[SMGENERIC_JSON] + if !hasKey { + return nil, nil + } + cfg := new(SmGenericJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil +} + func (self CgrJsonCfg) SmFsJsonCfg() (*SmFsJsonCfg, error) { rawCfg, hasKey := self[SMFS_JSN] if !hasKey { diff --git a/config/config_json_test.go b/config/config_json_test.go index fc5cbd75f..703307599 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -323,6 +323,22 @@ func TestDfCdrcJsonCfg(t *testing.T) { } } +func TestSmGenericJsonCfg(t *testing.T) { + eCfg := &SmGenericJsonCfg{ + Enabled: utils.BoolPointer(false), + Rater: utils.StringPointer("internal"), + Cdrs: utils.StringPointer("internal"), + Debit_interval: utils.StringPointer("10s"), + Min_call_duration: utils.StringPointer("0s"), + Max_call_duration: utils.StringPointer("3h"), + } + if cfg, err := dfCgrJsonCfg.SmGenericJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + func TestSmFsJsonCfg(t *testing.T) { eCfg := &SmFsJsonCfg{ Enabled: utils.BoolPointer(false), diff --git a/config/libconfig_json.go b/config/libconfig_json.go index d4b3f282e..92f3faa20 100644 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -159,6 +159,16 @@ type CdrcJsonCfg struct { Trailer_fields *[]*CdrFieldJsonCfg } +// SM-Generic config section +type SmGenericJsonCfg struct { + Enabled *bool + Rater *string + Cdrs *string + Debit_interval *string + Min_call_duration *string + Max_call_duration *string +} + // SM-FreeSWITCH config section type SmFsJsonCfg struct { Enabled *bool diff --git a/config/smconfig.go b/config/smconfig.go index fcc922996..ab6f2df0f 100644 --- a/config/smconfig.go +++ b/config/smconfig.go @@ -71,6 +71,47 @@ func (self *FsConnConfig) loadFromJsonCfg(jsnCfg *FsConnJsonCfg) error { return nil } +type SmGenericConfig struct { + Enabled bool + HaRater []*HaPoolConfig + HaCdrs []*HaPoolConfig + DebitInterval time.Duration + MinCallDuration time.Duration + MaxCallDuration time.Duration +} + +func (self *SmGenericConfig) loadFromJsonCfg(jsnCfg *SmGenericJsonCfg) error { + if jsnCfg == nil { + return nil + } + var err error + if jsnCfg.Enabled != nil { + self.Enabled = *jsnCfg.Enabled + } + if jsnCfg.Rater != nil { + self.HaRater = []*HaPoolConfig{&HaPoolConfig{Server: *jsnCfg.Rater, Timeout: time.Duration(1) * time.Second}} + } + if jsnCfg.Cdrs != nil { + self.HaCdrs = []*HaPoolConfig{&HaPoolConfig{Server: *jsnCfg.Cdrs, Timeout: time.Duration(1) * time.Second}} + } + if jsnCfg.Debit_interval != nil { + if self.DebitInterval, err = utils.ParseDurationWithSecs(*jsnCfg.Debit_interval); err != nil { + return err + } + } + if jsnCfg.Min_call_duration != nil { + if self.MinCallDuration, err = utils.ParseDurationWithSecs(*jsnCfg.Min_call_duration); err != nil { + return err + } + } + if jsnCfg.Max_call_duration != nil { + if self.MaxCallDuration, err = utils.ParseDurationWithSecs(*jsnCfg.Max_call_duration); err != nil { + return err + } + } + return nil +} + type SmFsConfig struct { Enabled bool HaRater []*HaPoolConfig