From ad682a5aed2a67753b904b6d3d53773808a2c793 Mon Sep 17 00:00:00 2001 From: DanB Date: Thu, 13 Aug 2015 12:16:30 +0200 Subject: [PATCH 1/6] LcrReq parameter change StartTime->SetupTime for uniformity with MaxUsageReq --- apier/v1/lcr.go | 6 ++++-- engine/lcr.go | 6 +++--- engine/lcr_test.go | 4 ++-- general_tests/tutorial_kam_calls_test.go | 2 ++ sessionmanager/fsevent.go | 2 +- sessionmanager/kamevent.go | 2 +- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/apier/v1/lcr.go b/apier/v1/lcr.go index 513bc64e0..2b8966ac1 100644 --- a/apier/v1/lcr.go +++ b/apier/v1/lcr.go @@ -68,9 +68,11 @@ func (self *ApierV1) GetLcrSuppliers(lcrReq engine.LcrRequest, suppliers *string if err := self.Responder.GetLCR(&engine.AttrGetLcr{CallDescriptor: cd, Paginator: lcrReq.Paginator}, &lcrQried); err != nil { return utils.NewErrServerError(err) } - if lcrQried.HasErrors() && !lcrReq.IgnoreErrors { + if lcrQried.HasErrors() { lcrQried.LogErrors() - return fmt.Errorf("%s:%s", utils.ErrServerError.Error(), "LCR_ERRORS") + if !lcrReq.IgnoreErrors { + return fmt.Errorf("%s:%s", utils.ErrServerError.Error(), "LCR_COMPUTE_ERRORS") + } } if suppliersStr, err := lcrQried.SuppliersString(); err != nil { return utils.NewErrServerError(err) diff --git a/engine/lcr.go b/engine/lcr.go index f5925d256..b2df016e3 100644 --- a/engine/lcr.go +++ b/engine/lcr.go @@ -54,7 +54,7 @@ type LcrRequest struct { Account string Subject string Destination string - StartTime string + SetupTime string Duration string IgnoreErrors bool *utils.Paginator @@ -79,9 +79,9 @@ func (self *LcrRequest) AsCallDescriptor() (*CallDescriptor, error) { } var timeStart time.Time var err error - if len(self.StartTime) == 0 { + if len(self.SetupTime) == 0 { timeStart = time.Now() - } else if timeStart, err = utils.ParseTimeDetectLayout(self.StartTime); err != nil { + } else if timeStart, err = utils.ParseTimeDetectLayout(self.SetupTime); err != nil { return nil, err } var callDur time.Duration diff --git a/engine/lcr_test.go b/engine/lcr_test.go index 1bd083d87..79f036087 100644 --- a/engine/lcr_test.go +++ b/engine/lcr_test.go @@ -215,11 +215,11 @@ func TestLcrGet(t *testing.T) { func TestLcrRequestAsCallDescriptor(t *testing.T) { sTime := time.Date(2015, 04, 06, 17, 40, 0, 0, time.UTC) callDur := time.Duration(1) * time.Minute - lcrReq := &LcrRequest{Account: "2001", StartTime: sTime.String()} + lcrReq := &LcrRequest{Account: "2001", SetupTime: sTime.String()} if _, err := lcrReq.AsCallDescriptor(); err == nil || err != utils.ErrMandatoryIeMissing { t.Error("Unexpected error received: %v", err) } - lcrReq = &LcrRequest{Account: "2001", Destination: "2002", StartTime: sTime.String()} + lcrReq = &LcrRequest{Account: "2001", Destination: "2002", SetupTime: sTime.String()} eCd := &CallDescriptor{ Direction: utils.OUT, Tenant: config.CgrConfig().DefaultTenant, diff --git a/general_tests/tutorial_kam_calls_test.go b/general_tests/tutorial_kam_calls_test.go index a4dba99b3..5bdc35ebe 100644 --- a/general_tests/tutorial_kam_calls_test.go +++ b/general_tests/tutorial_kam_calls_test.go @@ -508,6 +508,7 @@ func TestTutKamCallsCdrs(t *testing.T) { } } +/* // Make sure all stats queues were updated func TestTutKamCallsCdrStatsAfter(t *testing.T) { if !*testCalls { @@ -557,6 +558,7 @@ func TestTutKamCallsCdrStatsAfter(t *testing.T) { t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) } } +*/ // Make sure account was debited properly func TestTutKamCallsAccountFraud1001(t *testing.T) { diff --git a/sessionmanager/fsevent.go b/sessionmanager/fsevent.go index 914c6e806..2e1273aec 100644 --- a/sessionmanager/fsevent.go +++ b/sessionmanager/fsevent.go @@ -386,7 +386,7 @@ func (fsev FSEvent) AsCallDescriptor() (*engine.CallDescriptor, error) { Account: fsev.GetAccount(utils.META_DEFAULT), Subject: fsev.GetSubject(utils.META_DEFAULT), Destination: fsev.GetDestination(utils.META_DEFAULT), - StartTime: utils.FirstNonEmpty(fsev[SETUP_TIME], fsev[ANSWER_TIME]), + SetupTime: utils.FirstNonEmpty(fsev[SETUP_TIME], fsev[ANSWER_TIME]), Duration: fsev[DURATION], } return lcrReq.AsCallDescriptor() diff --git a/sessionmanager/kamevent.go b/sessionmanager/kamevent.go index 2ec757dcf..07669b43e 100644 --- a/sessionmanager/kamevent.go +++ b/sessionmanager/kamevent.go @@ -381,7 +381,7 @@ func (kev KamEvent) AsCallDescriptor() (*engine.CallDescriptor, error) { Account: kev.GetAccount(utils.META_DEFAULT), Subject: kev.GetSubject(utils.META_DEFAULT), Destination: kev.GetDestination(utils.META_DEFAULT), - StartTime: utils.FirstNonEmpty(kev[CGR_SETUPTIME], kev[CGR_ANSWERTIME]), + SetupTime: utils.FirstNonEmpty(kev[CGR_SETUPTIME], kev[CGR_ANSWERTIME]), Duration: kev[CGR_DURATION], } return lcrReq.AsCallDescriptor() From 2aebd5e080b36f9aeb4ff0be9ea3308576f31e94 Mon Sep 17 00:00:00 2001 From: DanB Date: Mon, 17 Aug 2015 12:50:33 +0200 Subject: [PATCH 2/6] Improved tutorial calls tests --- .../freeswitch/etc/freeswitch_conf.tar.gz | Bin 28272 -> 28299 bytes general_tests/tutorial_fs_calls_test.go | 131 +++++-- general_tests/tutorial_kam_calls_test.go | 326 +++++++++--------- general_tests/tutorial_osips_calls_test.go | 232 ++++++++++--- 4 files changed, 456 insertions(+), 233 deletions(-) diff --git a/data/tutorials/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz b/data/tutorials/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz index f6212599410880d5e7d7a1a2f34eec63d79d5b6b..777211ea0e1e31f10e6bd3f1b2f19b95ec916108 100644 GIT binary patch delta 9425 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 delta 9442 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%0D+GuGM)HGV?sz{dM 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 oxSuD#|FU; Date: Mon, 17 Aug 2015 13:06:52 +0200 Subject: [PATCH 3/6] ApierV1.SetAccount - add Disabled option, proper AllowNegative implementation --- apier/v1/accounts.go | 9 +++++++-- utils/apitpdata.go | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apier/v1/accounts.go b/apier/v1/accounts.go index f9c3b53ed..b8702597c 100644 --- a/apier/v1/accounts.go +++ b/apier/v1/accounts.go @@ -168,8 +168,7 @@ func (self *ApierV1) SetAccount(attr utils.AttrSetAccount, reply *string) error ub = bal } else { // Not found in db, create it here ub = &engine.Account{ - Id: balanceId, - AllowNegative: attr.AllowNegative, + Id: balanceId, } } @@ -183,6 +182,12 @@ func (self *ApierV1) SetAccount(attr utils.AttrSetAccount, reply *string) error at.AccountIds = append(at.AccountIds, balanceId) } } + if attr.AllowNegative != nil { + ub.AllowNegative = *attr.AllowNegative + } + if attr.Disabled != nil { + ub.Disabled = *attr.Disabled + } // All prepared, save account if err := self.AccountDb.SetAccount(ub); err != nil { return 0, err diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 3adbde62a..861242b50 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -1080,7 +1080,8 @@ type AttrSetAccount struct { Direction string Account string ActionPlanId string - AllowNegative bool + AllowNegative *bool + Disabled *bool } type AttrRemoveAccount struct { From 5149b080c079166b6bdf86c70d8d307142bafd79 Mon Sep 17 00:00:00 2001 From: DanB Date: Tue, 18 Aug 2015 13:05:34 +0200 Subject: [PATCH 4/6] New kamailio tutorial in docs, various doc improvements, fixes in local calls --- .../freeswitch/etc/freeswitch_conf.tar.gz | Bin 28299 -> 28291 bytes .../kamailio/etc/kamailio/kamailio.cfg | 2 +- docs/installation.rst | 11 ++-- docs/tut_freeswitch.rst | 5 +- docs/tut_freeswitch_json.rst | 12 ++-- docs/tut_opensips_event.rst | 12 ++-- docs/tut_opensips_installs.rst | 4 +- docs/tutorials.rst | 1 + general_tests/tutorial_fs_calls_test.go | 3 +- general_tests/tutorial_kam_calls_test.go | 53 +++++++++--------- general_tests/tutorial_osips_calls_test.go | 27 +++++---- 11 files changed, 65 insertions(+), 65 deletions(-) diff --git a/data/tutorials/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz b/data/tutorials/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz index 777211ea0e1e31f10e6bd3f1b2f19b95ec916108..310388a91667dd05bd8eee2bccef9d42c3c33f3b 100644 GIT binary patch delta 9486 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 ghX>F4-}C4B^Za@KJb#`)ztrb{0j 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 diff --git a/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio.cfg b/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio.cfg index a61eea930..1c962a6aa 100644 --- a/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio.cfg +++ b/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio.cfg @@ -60,7 +60,7 @@ loadmodule "jsonrpc-s.so" # ----------------- setting module-specific parameters --------------- # ----- mi_fifo params ----- -modparam("mi_fifo", "fifo_name", "/tmp/cgr_kamevapi/kamailio/run/kamailio_fifo") +modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") # ----- tm params ----- modparam("tm", "failure_reply_mode", 3) diff --git a/docs/installation.rst b/docs/installation.rst index 9179ed1d0..56d6c0ea3 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -45,18 +45,20 @@ Database setup ~~~~~~~~~~~~~~ For it's operation CGRateS uses more database types, depending on it's nature, install and configuration being further necessary. + At present we support the following databases: -As DataDB types (rating and accounting subsystems): + - Redis_ -As StorDB (persistent storage for CDRs and tariff plan versions). - +Used as DataDb, optimized for real-time information access. Once installed there should be no special requirements in terms of setup since no schema is necessary. + - MySQL_ +Used as StorDb, optimized for CDR archiving and offline Tariff Plan versioning. Once database is installed, CGRateS database needs to be set-up out of provided scripts (example for the paths set-up by debian package) :: @@ -66,12 +68,13 @@ Once database is installed, CGRateS database needs to be set-up out of provided - PostgreSQL_ +Used as StorDb, optimized for CDR archiving and offline Tariff Plan versioning. Once database is installed, CGRateS database needs to be set-up out of provided scripts (example for the paths set-up by debian package) :: cd /usr/share/cgrates/storage/postgres/ - ./setup_cgr_db.sh root CGRateS.org localhost + ./setup_cgr_db.sh .. _Redis: http://redis.io/ .. _MySQL: http://www.mysql.org/ diff --git a/docs/tut_freeswitch.rst b/docs/tut_freeswitch.rst index e03b9c859..dc54b7bdd 100644 --- a/docs/tut_freeswitch.rst +++ b/docs/tut_freeswitch.rst @@ -1,7 +1,7 @@ -sFreeSWITCH Integration Tutorials +FreeSWITCH Integration Tutorials ================================ -In these tutorials we exemplify few cases of integration between FreeSWITCH_ and **CGRateS**. We start with common steps, installation and postinstall processes then we dive into particular configurations, depending on the case we run. +In these tutorials we exemplify few cases of integration between FreeSWITCH_ and **CGRateS**. We start with common steps, installation and postinstall processes then we dive into particular configurations. .. toctree:: @@ -10,7 +10,6 @@ In these tutorials we exemplify few cases of integration between FreeSWITCH_ and tut_freeswitch_installs tut_cgrates_installs tut_jitsi_installs - tut_freeswitch_csv tut_freeswitch_json tut_cgrates_usage diff --git a/docs/tut_freeswitch_json.rst b/docs/tut_freeswitch_json.rst index 0501bcb69..3d9479b9d 100644 --- a/docs/tut_freeswitch_json.rst +++ b/docs/tut_freeswitch_json.rst @@ -4,7 +4,7 @@ FreeSWITCH_ generating *http-json* CDRs Scenario -------- -- FreeSWITCH with *vanilla* configuration, replacing *mod_cdr_csv* with *mod_json_cdr*. +- FreeSWITCH with *vanilla* configuration adding *mod_json_cdr* for CDR generation. - Modified following users (with configs in *etc/freeswitch/directory/default*): 1001-prepaid, 1002-postpaid, 1003-pseudoprepaid, 1004-rated, 1006-prepaid, 1007-rated. - Have added inside default dialplan CGR own extensions just before routing towards users (*etc/freeswitch/dialplan/default.xml*). @@ -13,8 +13,8 @@ Scenario - **CGRateS** with following components: - CGR-SM started as prepaid controller, with debits taking place at 5s intervals. - - CGR-Mediator component attaching costs to the raw CDRs from FreeSWITCH_ inside CGR StorDB. - - CGR-CDRE exporting mediated CDRs from CGR StorDB (export path: */tmp*). + - CGR-CDRS component receiving raw CDRs from FreeSWITCH, storing them and attaching costs inside CGR StorDB. + - CGR-CDRE exporting processed CDRs from CGR StorDB (export path: */tmp*). - CGR-History component keeping the archive of the rates modifications (path browsable with git client at */tmp/cgr_history*). @@ -23,7 +23,7 @@ Starting FreeSWITCH_ with custom configuration :: - /usr/share/cgrates/tutorials/fs_json/freeswitch/etc/init.d/freeswitch start + /usr/share/cgrates/tutorials/fs_evsock/freeswitch/etc/init.d/freeswitch start To verify that FreeSWITCH_ is running we run the console command: @@ -37,7 +37,7 @@ Starting **CGRateS** with custom configuration :: - /usr/share/cgrates/tutorials/fs_json/cgrates/etc/init.d/cgrates start + /usr/share/cgrates/tutorials/fs_evsock/cgrates/etc/init.d/cgrates start Check that cgrates is running @@ -49,7 +49,7 @@ Check that cgrates is running CDR processing -------------- -At the end of each call FreeSWITCH_ will issue a http post with the CDR. This will reach inside **CGRateS** through the *CDRS* component (close to real-time). Once in-there it will be instantly mediated and it is ready to be exported: +At the end of each call FreeSWITCH_ will issue a http post with the CDR. This will reach inside **CGRateS** through the *CDRS* component (close to real-time). Once in-there it will be instantly rated and it is ready to be exported: :: diff --git a/docs/tut_opensips_event.rst b/docs/tut_opensips_event.rst index ca94318fd..9f7473a35 100644 --- a/docs/tut_opensips_event.rst +++ b/docs/tut_opensips_event.rst @@ -12,8 +12,8 @@ Scenario - **CGRateS** with following components: - CGR-SM started as translator between OpenSIPS_ and **cgr-rater** for both authorization events (pseudoprepaid) as well as CDR ones. - - CGR-Mediator component attaching costs to the raw CDRs from OpenSIPS_ inside CGR StorDB. - - CGR-CDRE exporting mediated CDRs from CGR StorDB (export path: */tmp*). + - CGR-CDRS component processing raw CDRs from CGR-SM component and storing them inside CGR StorDB. + - CGR-CDRE exporting rated CDRs from CGR StorDB (export path: */tmp*). - CGR-History component keeping the archive of the rates modifications (path browsable with git client at */tmp/cgr_history*). @@ -22,7 +22,7 @@ Starting OpenSIPS_ with custom configuration :: - /usr/share/cgrates/tutorials/osips_event/opensips/etc/init.d/opensips start + /usr/share/cgrates/tutorials/osips_async/opensips/etc/init.d/opensips start To verify that OpenSIPS_ is running we run the console command: @@ -36,9 +36,9 @@ Starting **CGRateS** with custom configuration :: - /usr/share/cgrates/tutorials/osips_event/cgrates/etc/init.d/cgrates start + /usr/share/cgrates/tutorials/osips_async/cgrates/etc/init.d/cgrates start -Check that cgrates is running +Make sure that cgrates is running :: @@ -48,7 +48,7 @@ Check that cgrates is running CDR processing -------------- -At the end of each call OpenSIPS_ will generate an CDR event and due to automatic handler registration built in **CGRateS-SM** component, this will be directed towards the port configured inside *cgrates.cfg*. This event will reach inside **CGRateS** through the *SM* component (close to real-time). Once in-there it will be instantly mediated and it is ready to be exported. +At the end of each call OpenSIPS_ will generate an CDR event and due to automatic handler registration built in **CGRateS-SM** component, this will be directed towards the port configured inside *cgrates.json*. This event will reach inside **CGRateS** through the *SM* component (close to real-time). Once in-there it will be instantly rated and be ready for export. **CGRateS** Usage diff --git a/docs/tut_opensips_installs.rst b/docs/tut_opensips_installs.rst index 89aa1a6cc..2080e548e 100644 --- a/docs/tut_opensips_installs.rst +++ b/docs/tut_opensips_installs.rst @@ -12,9 +12,9 @@ We got OpenSIPS_ installed via following commands: wget http://apt.opensips.org/key.asc apt-key add key.asc cd /etc/apt/sources.list.d/ - wget http://apt.itsyscom.com/conf/opensips.apt.list + wget http://apt.itsyscom.com/conf/opensips.wheezy.apt.list apt-get update - apt-get install + apt-get install opensips opensips-json-module opensips-restclient-module Once installed we proceed with loading the configuration out of specific tutorial cases bellow. diff --git a/docs/tutorials.rst b/docs/tutorials.rst index ff937c41e..8e5d72b64 100644 --- a/docs/tutorials.rst +++ b/docs/tutorials.rst @@ -5,4 +5,5 @@ :maxdepth: 2 tut_freeswitch + tut_kamailio tut_opensips diff --git a/general_tests/tutorial_fs_calls_test.go b/general_tests/tutorial_fs_calls_test.go index 7183a3f34..54835be23 100644 --- a/general_tests/tutorial_fs_calls_test.go +++ b/general_tests/tutorial_fs_calls_test.go @@ -99,8 +99,7 @@ func TestTutFsCallsRestartFS(t *testing.T) { if !*testCalls { return } - engine.KillProcName("freeswitch", 5000) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "start", 3000); err != nil { + if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "start", 5000); err != nil { t.Fatal(err) } } diff --git a/general_tests/tutorial_kam_calls_test.go b/general_tests/tutorial_kam_calls_test.go index de34bbff0..12ce0cfb9 100644 --- a/general_tests/tutorial_kam_calls_test.go +++ b/general_tests/tutorial_kam_calls_test.go @@ -44,7 +44,7 @@ func TestTutKamCallsInitCfg(t *testing.T) { } // Init config first var err error - tutKamCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*dataDir, "tutorials", "fs_evsock", "cgrates", "etc", "cgrates")) + tutKamCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*dataDir, "tutorials", "kamevapi", "cgrates", "etc", "cgrates")) if err != nil { t.Error(err) } @@ -73,12 +73,12 @@ func TestTutKamCallsResetStorDb(t *testing.T) { } // start FS server -func TestTutKamCallsStartFS(t *testing.T) { +func TestTutKamCallsStartKamailio(t *testing.T) { if !*testCalls { return } - engine.KillProcName("freeswitch", 5000) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "start", 3000); err != nil { + engine.KillProcName("kamailio", 3000) + if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "kamailio", "etc", "init.d", "kamailio"), "start", 2000); err != nil { t.Fatal(err) } } @@ -89,18 +89,17 @@ func TestTutKamCallsStartEngine(t *testing.T) { return } engine.KillProcName("cgr-engine", *waitRater) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil { + if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil { t.Fatal(err) } } // Restart FS so we make sure reconnects are working -func TestTutKamCallsRestartFS(t *testing.T) { +func TestTutKamCallsRestartKamailio(t *testing.T) { if !*testCalls { return } - engine.KillProcName("freeswitch", 5000) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "start", 3000); err != nil { + if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "kamailio", "etc", "init.d", "kamailio"), "restart", 3000); err != nil { t.Fatal(err) } } @@ -226,12 +225,12 @@ func TestTutKamCallsStartPjsuaListener(t *testing.T) { } var err error acnts := []*engine.PjsuaAccount{ - &engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}} + &engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, + &engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, + &engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, + &engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, + &engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, + &engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}} if tutKamCallsPjSuaListener, err = engine.StartPjsuaListener(acnts, 5070, *waitRater); err != nil { t.Fatal(err) } @@ -242,7 +241,7 @@ func TestTutKamCallsCall1001To1002(t *testing.T) { if !*testCalls { return } - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1", + if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1", "sip:127.0.0.1:5060", time.Duration(67)*time.Second, 5071); err != nil { t.Fatal(err) } @@ -253,7 +252,7 @@ func TestTutKamCallsCall1001To1003(t *testing.T) { if !*testCalls { return } - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*"}, "sip:1003@127.0.0.1", + if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*"}, "sip:1003@127.0.0.1", "sip:127.0.0.1:5060", time.Duration(65)*time.Second, 5072); err != nil { t.Fatal(err) } @@ -263,7 +262,7 @@ func TestTutKamCallsCall1002To1001(t *testing.T) { if !*testCalls { return } - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1", + if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1", "sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5073); err != nil { t.Fatal(err) } @@ -273,7 +272,7 @@ func TestTutKamCallsCall1003To1001(t *testing.T) { if !*testCalls { return } - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1", + if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1", "sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5074); err != nil { t.Fatal(err) } @@ -283,7 +282,7 @@ func TestTutKamCallsCall1004To1001(t *testing.T) { if !*testCalls { return } - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1", + if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1", "sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5075); err != nil { t.Fatal(err) } @@ -293,7 +292,7 @@ func TestTutKamCallsCall1006To1002(t *testing.T) { if !*testCalls { return } - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1", + if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1", "sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5076); err != nil { t.Fatal(err) } @@ -303,7 +302,7 @@ func TestTutKamCallsCall1007To1002(t *testing.T) { if !*testCalls { return } - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1", + if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1", "sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5077); err != nil { t.Fatal(err) } @@ -341,7 +340,7 @@ func TestTutKamCalls1001Cdrs(t *testing.T) { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { cgrId = reply[0].CgrId - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_PREPAID { @@ -415,7 +414,7 @@ func TestTutKamCalls1002Cdrs(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_POSTPAID { @@ -442,7 +441,7 @@ func TestTutKamCalls1003Cdrs(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_PSEUDOPREPAID { @@ -470,7 +469,7 @@ func TestTutKamCalls1004Cdrs(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_RATED { @@ -498,7 +497,7 @@ func TestTutKamCalls1006Cdrs(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_PREPAID { @@ -528,7 +527,7 @@ func TestTutKamCalls1007Cdrs(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_PREPAID { diff --git a/general_tests/tutorial_osips_calls_test.go b/general_tests/tutorial_osips_calls_test.go index 7a7fdceae..25fa947de 100644 --- a/general_tests/tutorial_osips_calls_test.go +++ b/general_tests/tutorial_osips_calls_test.go @@ -44,7 +44,7 @@ func TestTutOsipsCallsInitCfg(t *testing.T) { } // Init config first var err error - tutOsipsCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*dataDir, "tutorials", "fs_evsock", "cgrates", "etc", "cgrates")) + tutOsipsCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*dataDir, "tutorials", "osips_async", "cgrates", "etc", "cgrates")) if err != nil { t.Error(err) } @@ -73,12 +73,12 @@ func TestTutOsipsCallsResetStorDb(t *testing.T) { } // start FS server -func TestTutOsipsCallsStartFS(t *testing.T) { +func TestTutOsipsCallsStartOsips(t *testing.T) { if !*testCalls { return } - engine.KillProcName("freeswitch", 5000) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "start", 3000); err != nil { + engine.KillProcName("opensips", 3000) + if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "opensips", "etc", "init.d", "opensips"), "start", 3000); err != nil { t.Fatal(err) } } @@ -89,18 +89,17 @@ func TestTutOsipsCallsStartEngine(t *testing.T) { return } engine.KillProcName("cgr-engine", *waitRater) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil { + if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil { t.Fatal(err) } } // Restart FS so we make sure reconnects are working -func TestTutOsipsCallsRestartFS(t *testing.T) { +func TestTutOsipsCallsRestartOsips(t *testing.T) { if !*testCalls { return } - engine.KillProcName("freeswitch", 5000) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "start", 3000); err != nil { + if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "opensips", "etc", "init.d", "opensips"), "restart", 3000); err != nil { t.Fatal(err) } } @@ -341,7 +340,7 @@ func TestTutOsipsCalls1001Cdrs(t *testing.T) { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { cgrId = reply[0].CgrId - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_PREPAID { @@ -415,7 +414,7 @@ func TestTutOsipsCalls1002Cdrs(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_POSTPAID { @@ -442,7 +441,7 @@ func TestTutOsipsCalls1003Cdrs(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_PSEUDOPREPAID { @@ -470,7 +469,7 @@ func TestTutOsipsCalls1004Cdrs(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_RATED { @@ -498,7 +497,7 @@ func TestTutOsipsCalls1006Cdrs(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_PREPAID { @@ -528,7 +527,7 @@ func TestTutOsipsCalls1007Cdrs(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].CdrSource != "freeswitch_json" { + if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } if reply[0].ReqType != utils.META_PREPAID { From 18c3161b8dca255f0e45d3816eb143f3a5a2c189 Mon Sep 17 00:00:00 2001 From: DanB Date: Tue, 18 Aug 2015 13:06:05 +0200 Subject: [PATCH 5/6] Kamailio tutorial doc files --- docs/tut_kamailio.rst | 18 +++++++++++ docs/tut_kamailio_evapi.rst | 59 ++++++++++++++++++++++++++++++++++ docs/tut_kamailio_installs.rst | 20 ++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 docs/tut_kamailio.rst create mode 100644 docs/tut_kamailio_evapi.rst create mode 100644 docs/tut_kamailio_installs.rst diff --git a/docs/tut_kamailio.rst b/docs/tut_kamailio.rst new file mode 100644 index 000000000..035305881 --- /dev/null +++ b/docs/tut_kamailio.rst @@ -0,0 +1,18 @@ +Kamailio_ Integration Tutorials +=============================== + +In these tutorials we exemplify few cases of integration between Kamailio_ and CGRateS_. We start with common steps, installation and postinstall processes then we dive into particular configurations, depending on the case we run. + + +.. toctree:: + :maxdepth: 2 + + tut_kamailio_installs + tut_cgrates_installs + tut_jitsi_installs + tut_kamailio_evapi + tut_cgrates_usage + +.. _Kamailio: http://www.kamailio.org/ +.. _CGRateS: http://www.cgrates.org/ + diff --git a/docs/tut_kamailio_evapi.rst b/docs/tut_kamailio_evapi.rst new file mode 100644 index 000000000..04df505ff --- /dev/null +++ b/docs/tut_kamailio_evapi.rst @@ -0,0 +1,59 @@ +Kamailio_ interaction via *evapi* module +========================================= + +Scenario +-------- + + - Kamailio default configuration modified for **CGRateS** interaction. For script maintainability and simplicity we have separated CGRateS specific routes in *kamailio-cgrates.cfg* file which is included in main *kamailio.cfg* via include directive. + + - Considering the following users (with configs hardcoded in the *kamailio.cfg* configuration script and loaded in htable): 1001-prepaid, 1002-postpaid, 1003-pseudoprepaid, 1004-rated, 1005-rated, 1006-prepaid, 1007-prepaid. + +- **CGRateS** with following components: + + - CGR-SM started as translator between Kamailio_ and CGR-Rater for both authorization events as well as accounting ones. + - CGR-CDRS component processing raw CDRs from CGR-SM component and storing them inside CGR StorDB. + - CGR-CDRE exporting rated CDRs from CGR StorDB (export path: */tmp*). + - CGR-History component keeping the archive of the rates modifications (path browsable with git client at */tmp/cgr_history*). + + +Starting Kamailio_ with custom configuration +---------------------------------------------- + +:: + + /usr/share/cgrates/tutorials/kamevapi/kamailio/etc/init.d/kamailio start + +To verify that Kamailio_ is running we run the console command: + +:: + + kamctl moni + + +Starting **CGRateS** with custom configuration +---------------------------------------------- + +:: + + /usr/share/cgrates/tutorials/kamevapi/cgrates/etc/init.d/cgrates start + +Make sure that cgrates is running + +:: + + cgr-console status + + +CDR processing +-------------- + +At the end of each call Kamailio_ will generate an CDR event via *evapi* and this will be directed towards the port configured inside *cgrates.json*. This event will reach inside **CGRateS** through the *SM* component (close to real-time). Once in-there it will be instantly rated and be ready for export. + + +**CGRateS** Usage +----------------- + +Since it is common to most of the tutorials, the example for **CGRateS** usage is provided in a separate page `here `_ + + +.. _Kamailio: http://www.kamailio.org/ diff --git a/docs/tut_kamailio_installs.rst b/docs/tut_kamailio_installs.rst new file mode 100644 index 000000000..ff44d32e1 --- /dev/null +++ b/docs/tut_kamailio_installs.rst @@ -0,0 +1,20 @@ +Software installation +===================== + +As operating system we have choosen Debian Wheezy, since all the software components we use provide packaging for it. + +Kamailio_ +--------- + +We got Kamailio_ installed via following commands: +:: + + apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xfb40d3e6508ea4c8 + cd /etc/apt/sources.list.d/ + wget http://apt.itsyscom.com/conf/kamailio.apt.list . + apt-get update + apt-get install kamailio kamailio-extra-modules kamailio-json-modules + +Once installed we proceed with loading the configuration out of specific tutorial cases bellow. + +.. _Kamailio: http://www.kamailio.org/ \ No newline at end of file From 9db4948f3b802b1ee9d7608f4df6b8a96e305ed6 Mon Sep 17 00:00:00 2001 From: DanB Date: Tue, 18 Aug 2015 13:38:04 +0200 Subject: [PATCH 6/6] Small fix tutorial fs --- general_tests/tutorial_fs_calls_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general_tests/tutorial_fs_calls_test.go b/general_tests/tutorial_fs_calls_test.go index 54835be23..6ae5fa55f 100644 --- a/general_tests/tutorial_fs_calls_test.go +++ b/general_tests/tutorial_fs_calls_test.go @@ -99,7 +99,7 @@ func TestTutFsCallsRestartFS(t *testing.T) { if !*testCalls { return } - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "start", 5000); err != nil { + if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "restart", 5000); err != nil { t.Fatal(err) } }