Example #1
0
func startSmFreeSWITCH(internalRaterChan chan *engine.Responder, cdrDb engine.CdrStorage, exitChan chan bool) {
	engine.Logger.Info("Starting CGRateS SM-FreeSWITCH service.")
	var raterConn, cdrsConn engine.ConnectorPool
	var client *rpcclient.RpcClient
	var err error
	delay := utils.Fib()
	for _, raterCfg := range cfg.SmFsConfig.HaRater {
		if raterCfg.Server == utils.INTERNAL {
			resp := <-internalRaterChan
			raterConn = append(raterConn, resp)
			internalRaterChan <- resp
		}
		for i := 0; i < cfg.Reconnects; i++ {
			client, err = rpcclient.NewRpcClient("tcp", raterCfg.Server, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB)
			if err == nil { //Connected so no need to reiterate
				break
			}
			time.Sleep(delay())
		}
		if err != nil {
			engine.Logger.Crit(fmt.Sprintf("<SM-FreeSWITCH> Could not connect to rater via RPC: %v", err))
			exitChan <- true
			return
		}
		raterConn = append(raterConn, &engine.RPCClientConnector{Client: client, Timeout: raterCfg.Timeout})
	}
	if reflect.DeepEqual(cfg.SmFsConfig.HaCdrs, cfg.SmFsConfig.HaRater) {
		cdrsConn = raterConn
	} else if len(cfg.SmFsConfig.HaCdrs) != 0 {
		delay = utils.Fib()
		for _, cdrsCfg := range cfg.SmFsConfig.HaCdrs {
			if cdrsCfg.Server == utils.INTERNAL {
				resp := <-internalRaterChan
				raterConn = append(raterConn, resp)
				internalRaterChan <- resp
			}
			for i := 0; i < cfg.Reconnects; i++ {
				client, err = rpcclient.NewRpcClient("tcp", cdrsCfg.Server, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB)
				if err == nil { //Connected so no need to reiterate
					break
				}
				time.Sleep(delay())
			}
			if err != nil {
				engine.Logger.Crit(fmt.Sprintf("<SM-FreeSWITCH> Could not connect to CDRS via RPC: %v", err))
				exitChan <- true
				return
			}
			cdrsConn = append(cdrsConn, &engine.RPCClientConnector{Client: client, Timeout: cdrsCfg.Timeout})

		}
	}
	sm := sessionmanager.NewFSSessionManager(cfg.SmFsConfig, raterConn, cdrsConn, cfg.DefaultTimezone)
	sms = append(sms, sm)
	smRpc.SMs = append(smRpc.SMs, sm)
	if err = sm.Connect(); err != nil {
		engine.Logger.Err(fmt.Sprintf("<SessionManager> error: %s!", err))
	}
	exitChan <- true
}
Example #2
0
func NewRPCPool(dispatchStrategy string, connAttempts, reconnects int, connectTimeout, replyTimeout time.Duration,
	rpcConnCfgs []*config.HaPoolConfig, internalConnChan chan rpcclient.RpcClientConnection, ttl time.Duration) (*rpcclient.RpcClientPool, error) {
	var rpcClient *rpcclient.RpcClient
	var err error
	rpcPool := rpcclient.NewRpcClientPool(dispatchStrategy, replyTimeout)
	atLestOneConnected := false // If one connected we don't longer return errors
	for _, rpcConnCfg := range rpcConnCfgs {
		if rpcConnCfg.Address == utils.MetaInternal {
			var internalConn rpcclient.RpcClientConnection
			select {
			case internalConn = <-internalConnChan:
				internalConnChan <- internalConn
			case <-time.After(ttl):
				return nil, errors.New("TTL triggered")
			}
			rpcClient, err = rpcclient.NewRpcClient("", "", connAttempts, reconnects, connectTimeout, replyTimeout, rpcclient.INTERNAL_RPC, internalConn, false)
		} else if utils.IsSliceMember([]string{utils.MetaJSONrpc, utils.MetaGOBrpc, ""}, rpcConnCfg.Transport) {
			codec := utils.GOB
			if rpcConnCfg.Transport != "" {
				codec = rpcConnCfg.Transport[1:] // Transport contains always * before codec understood by rpcclient
			}
			rpcClient, err = rpcclient.NewRpcClient("tcp", rpcConnCfg.Address, connAttempts, reconnects, connectTimeout, replyTimeout, codec, nil, false)
		} else {
			return nil, fmt.Errorf("Unsupported transport: <%s>", rpcConnCfg.Transport)
		}
		if err == nil {
			atLestOneConnected = true
		}
		rpcPool.AddClient(rpcClient)
	}
	if atLestOneConnected {
		err = nil
	}
	return rpcPool, err
}
Example #3
0
func startDiameterAgent(internalSMGChan chan rpcclient.RpcClientConnection, exitChan chan bool) {
	utils.Logger.Info("Starting CGRateS DiameterAgent service.")
	var smgConn *rpcclient.RpcClient
	var err error
	if cfg.DiameterAgentCfg().SMGeneric == utils.INTERNAL {
		smgRpc := <-internalSMGChan
		internalSMGChan <- smgRpc
		smgConn, err = rpcclient.NewRpcClient("", "", 0, 0, rpcclient.INTERNAL_RPC, smgRpc)
	} else {
		smgConn, err = rpcclient.NewRpcClient("tcp", cfg.DiameterAgentCfg().SMGeneric, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB, nil)
	}
	if err != nil {
		utils.Logger.Crit(fmt.Sprintf("<DiameterAgent> Could not connect to SMG: %s", err.Error()))
		exitChan <- true
		return
	}
	da, err := agents.NewDiameterAgent(cfg, smgConn)
	if err != nil {
		utils.Logger.Err(fmt.Sprintf("<DiameterAgent> error: %s!", err))
		exitChan <- true
		return
	}
	if err = da.ListenAndServe(); err != nil {
		utils.Logger.Err(fmt.Sprintf("<DiameterAgent> error: %s!", err))
	}
	exitChan <- true
}
Example #4
0
func startSmGeneric(internalSMGChan chan rpcclient.RpcClientConnection, internalRaterChan chan *engine.Responder, server *utils.Server, exitChan chan bool) {
	utils.Logger.Info("Starting CGRateS SM-Generic service.")
	var raterConn, cdrsConn engine.Connector
	var client *rpcclient.RpcClient
	var err error
	// Connect to rater
	for _, raterCfg := range cfg.SmGenericConfig.HaRater {
		if raterCfg.Server == utils.INTERNAL {
			resp := <-internalRaterChan
			raterConn = resp // Will overwrite here for the sake of keeping internally the new configuration format for ha connections
			internalRaterChan <- resp
		} else {
			client, err = rpcclient.NewRpcClient("tcp", raterCfg.Server, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB, nil)
			if err != nil { //Connected so no need to reiterate
				utils.Logger.Crit(fmt.Sprintf("<SM-Generic> Could not connect to Rater via RPC: %v", err))
				exitChan <- true
				return
			}
			raterConn = &engine.RPCClientConnector{Client: client}
		}
	}
	// Connect to CDRS
	if reflect.DeepEqual(cfg.SmGenericConfig.HaCdrs, cfg.SmGenericConfig.HaRater) {
		cdrsConn = raterConn
	} else if len(cfg.SmGenericConfig.HaCdrs) != 0 {
		for _, cdrsCfg := range cfg.SmGenericConfig.HaCdrs {
			if cdrsCfg.Server == utils.INTERNAL {
				resp := <-internalRaterChan
				cdrsConn = resp
				internalRaterChan <- resp
			} else {
				client, err = rpcclient.NewRpcClient("tcp", cdrsCfg.Server, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB, nil)
				if err != nil {
					utils.Logger.Crit(fmt.Sprintf("<SM-Generic> Could not connect to CDRS via RPC: %v", err))
					exitChan <- true
					return
				}
				cdrsConn = &engine.RPCClientConnector{Client: client}
			}
		}
	}
	smg_econns := sessionmanager.NewSMGExternalConnections()
	sm := sessionmanager.NewSMGeneric(cfg, raterConn, cdrsConn, cfg.DefaultTimezone, smg_econns)
	if err = sm.Connect(); err != nil {
		utils.Logger.Err(fmt.Sprintf("<SM-Generic> error: %s!", err))
	}
	// Register RPC handler
	smgRpc := v1.NewSMGenericV1(sm)
	server.RpcRegister(smgRpc)
	internalSMGChan <- smgRpc
	// Register BiRpc handlers
	smgBiRpc := v1.NewSMGenericBiRpcV1(sm)
	for method, handler := range smgBiRpc.Handlers() {
		server.BijsonRegisterName(method, handler)
	}
	// Register OnConnect handlers so we can intercept connections for session disconnects
	server.BijsonRegisterOnConnect(smg_econns.OnClientConnect)
	server.BijsonRegisterOnDisconnect(smg_econns.OnClientDisconnect)
}
// Connect rpc client to rater
func TestCdrsHttpCdrReplication(t *testing.T) {
	if !*testIntegration {
		return
	}
	cdrsMasterRpc, err := rpcclient.NewRpcClient("tcp", cdrsMasterCfg.RPCJSONListen, 1, 1, "json", nil)
	if err != nil {
		t.Fatal("Could not connect to rater: ", err.Error())
	}
	testCdr1 := &engine.CDR{CGRID: utils.Sha1("httpjsonrpc1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
		ToR: utils.VOICE, OriginID: "httpjsonrpc1", OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_PSEUDOPREPAID,
		Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
		SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC),
		Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
		RunID: utils.DEFAULT_RUNID, Cost: 1.201, Rated: true}
	var reply string
	if err := cdrsMasterRpc.Call("CdrsV2.ProcessCdr", testCdr1, &reply); err != nil {
		t.Error("Unexpected error: ", err.Error())
	} else if reply != utils.OK {
		t.Error("Unexpected reply received: ", reply)
	}
	time.Sleep(time.Duration(*waitRater) * time.Millisecond)
	cdrsSlaveRpc, err := rpcclient.NewRpcClient("tcp", "127.0.0.1:12012", 1, 1, "json", nil)
	if err != nil {
		t.Fatal("Could not connect to rater: ", err.Error())
	}
	// ToDo: Fix cdr_http to be compatible with rest of processCdr methods
	var rcvedCdrs []*engine.ExternalCDR
	if err := cdrsSlaveRpc.Call("ApierV2.GetCdrs", utils.RPCCDRsFilter{CGRIDs: []string{testCdr1.CGRID}, RunIDs: []string{utils.META_DEFAULT}}, &rcvedCdrs); err != nil {
		t.Error("Unexpected error: ", err.Error())
	} else if len(rcvedCdrs) != 1 {
		t.Error("Unexpected number of CDRs returned: ", len(rcvedCdrs))
	} else {
		rcvSetupTime, _ := utils.ParseTimeDetectLayout(rcvedCdrs[0].SetupTime, "")
		rcvAnswerTime, _ := utils.ParseTimeDetectLayout(rcvedCdrs[0].AnswerTime, "")
		//rcvUsage, _ := utils.ParseDurationWithSecs(rcvedCdrs[0].Usage)
		if rcvedCdrs[0].CGRID != testCdr1.CGRID ||
			rcvedCdrs[0].ToR != testCdr1.ToR ||
			rcvedCdrs[0].OriginHost != testCdr1.OriginHost ||
			rcvedCdrs[0].Source != testCdr1.Source ||
			rcvedCdrs[0].RequestType != testCdr1.RequestType ||
			rcvedCdrs[0].Direction != testCdr1.Direction ||
			rcvedCdrs[0].Tenant != testCdr1.Tenant ||
			rcvedCdrs[0].Category != testCdr1.Category ||
			rcvedCdrs[0].Account != testCdr1.Account ||
			rcvedCdrs[0].Subject != testCdr1.Subject ||
			rcvedCdrs[0].Destination != testCdr1.Destination ||
			!rcvSetupTime.Equal(testCdr1.SetupTime) ||
			!rcvAnswerTime.Equal(testCdr1.AnswerTime) ||
			//rcvUsage != 10 ||
			rcvedCdrs[0].RunID != testCdr1.RunID {
			//rcvedCdrs[0].Cost != testCdr1.Cost ||
			//!reflect.DeepEqual(rcvedCdrs[0].ExtraFields, testCdr1.ExtraFields) {
			t.Errorf("Expected: %+v, received: %+v", testCdr1, rcvedCdrs[0])
		}
	}
}
Example #6
0
func startSessionManager(responder *engine.Responder, loggerDb engine.LogStorage, cacheChan chan struct{}) {
	var raterConn, cdrsConn engine.Connector
	var client *rpcclient.RpcClient
	if cfg.SMRater == utils.INTERNAL {
		<-cacheChan // Wait for the cache to init before start doing queries
		raterConn = responder
	} else {
		var err error
		for i := 0; i < cfg.SMReconnects; i++ {
			client, err = rpcclient.NewRpcClient("tcp", cfg.SMRater, 0, cfg.SMReconnects, utils.GOB)
			if err == nil { //Connected so no need to reiterate
				break
			}
			time.Sleep(time.Duration(i+1) * time.Second)
		}
		if err != nil {
			engine.Logger.Crit(fmt.Sprintf("<SessionManager> Could not connect to engine: %v", err))
			exitChan <- true
		}
		raterConn = &engine.RPCClientConnector{Client: client}
	}
	if cfg.SMCdrS == cfg.SMRater {
		cdrsConn = raterConn
	} else if cfg.SMCdrS == utils.INTERNAL {
		<-cacheChan // Wait for the cache to init before start doing queries
		cdrsConn = responder
	} else if len(cfg.SMCdrS) != 0 {
		for i := 0; i < cfg.SMReconnects; i++ {
			client, err = rpcclient.NewRpcClient("tcp", cfg.SMCdrS, 0, cfg.SMReconnects, utils.GOB)
			if err == nil { //Connected so no need to reiterate
				break
			}
			time.Sleep(time.Duration(i+1) * time.Second)
		}
		if err != nil {
			engine.Logger.Crit(fmt.Sprintf("<SM-OpenSIPS> Could not connect to CDRS via RPC: %v", err))
			exitChan <- true
		}
		cdrsConn = &engine.RPCClientConnector{Client: client}
	}
	switch cfg.SMSwitchType {
	case FS:
		dp, _ := time.ParseDuration(fmt.Sprintf("%vs", cfg.SMDebitInterval))
		sm = sessionmanager.NewFSSessionManager(cfg, loggerDb, raterConn, cdrsConn, dp)
	case OSIPS:
		sm, _ = sessionmanager.NewOSipsSessionManager(cfg, raterConn, cdrsConn)
	default:
		engine.Logger.Err(fmt.Sprintf("<SessionManager> Unsupported session manger type: %s!", cfg.SMSwitchType))
		exitChan <- true
	}
	if err = sm.Connect(); err != nil {
		engine.Logger.Err(fmt.Sprintf("<SessionManager> error: %s!", err))
	}
	exitChan <- true
}
Example #7
0
func startSmOpenSIPS(internalRaterChan chan *engine.Responder, cdrDb engine.CdrStorage, exitChan chan bool) {
	utils.Logger.Info("Starting CGRateS SM-OpenSIPS service.")
	var raterConn, cdrsConn engine.Connector
	var client *rpcclient.RpcClient
	var err error
	// Connect to rater
	for _, raterCfg := range cfg.SmOsipsConfig.HaRater {
		if raterCfg.Server == utils.INTERNAL {
			resp := <-internalRaterChan
			raterConn = resp // Will overwrite here for the sake of keeping internally the new configuration format for ha connections
			internalRaterChan <- resp
		} else {
			client, err = rpcclient.NewRpcClient("tcp", raterCfg.Server, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB)
			if err != nil { //Connected so no need to reiterate
				utils.Logger.Crit(fmt.Sprintf("<SM-FreeSWITCH> Could not connect to rater via RPC: %v", err))
				exitChan <- true
				return
			}
			raterConn = &engine.RPCClientConnector{Client: client}
		}
	}
	// Connect to CDRS
	if reflect.DeepEqual(cfg.SmOsipsConfig.HaCdrs, cfg.SmOsipsConfig.HaRater) {
		cdrsConn = raterConn
	} else if len(cfg.SmOsipsConfig.HaCdrs) != 0 {
		for _, cdrsCfg := range cfg.SmOsipsConfig.HaCdrs {
			if cdrsCfg.Server == utils.INTERNAL {
				resp := <-internalRaterChan
				cdrsConn = resp
				internalRaterChan <- resp
			} else {
				client, err = rpcclient.NewRpcClient("tcp", cdrsCfg.Server, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB)
				if err != nil {
					utils.Logger.Crit(fmt.Sprintf("<SM-FreeSWITCH> Could not connect to CDRS via RPC: %v", err))
					exitChan <- true
					return
				}
				cdrsConn = &engine.RPCClientConnector{Client: client}
			}
		}
	}
	sm, _ := sessionmanager.NewOSipsSessionManager(cfg.SmOsipsConfig, cfg.Reconnects, raterConn, cdrsConn, cfg.DefaultTimezone)
	sms = append(sms, sm)
	smRpc.SMs = append(smRpc.SMs, sm)
	if err := sm.Connect(); err != nil {
		utils.Logger.Err(fmt.Sprintf("<SM-OpenSIPS> error: %s!", err))
	}
	exitChan <- true
}
Example #8
0
// Connect rpc client to rater
func TestRPCITLclRpcConnPoolFirst(t *testing.T) {
	rpcPoolFirst = rpcclient.NewRpcClientPool(rpcclient.POOL_FIRST, 0)
	rpcRAL1, err = rpcclient.NewRpcClient("tcp", rpcITCfg1.RPCJSONListen, 3, 1,
		time.Duration(1*time.Second), time.Duration(2*time.Second), rpcclient.JSON_RPC, nil, false)
	if err == nil {
		t.Fatal("Should receive cannot connect error here")
	}
	rpcPoolFirst.AddClient(rpcRAL1)
	rpcRAL2, err = rpcclient.NewRpcClient("tcp", rpcITCfg2.RPCJSONListen, 3, 1,
		time.Duration(1*time.Second), time.Duration(2*time.Second), rpcclient.JSON_RPC, nil, false)
	if err != nil {
		t.Fatal(err)
	}
	rpcPoolFirst.AddClient(rpcRAL2)
}
Example #9
0
func startMediator(responder *engine.Responder, loggerDb engine.LogStorage, cdrDb engine.CdrStorage, cacheChan, chanDone chan struct{}) {
	var connector engine.Connector
	if cfg.MediatorRater == utils.INTERNAL {
		<-cacheChan // Cache needs to come up before we are ready
		connector = responder
	} else {
		var client *rpcclient.RpcClient
		var err error

		for i := 0; i < cfg.MediatorReconnects; i++ {
			client, err = rpcclient.NewRpcClient("tcp", cfg.MediatorRater, 0, cfg.MediatorReconnects, utils.GOB)
			if err == nil { //Connected so no need to reiterate
				break
			}
			time.Sleep(time.Duration(i+1) * time.Second)
		}
		if err != nil {
			engine.Logger.Crit(fmt.Sprintf("<Mediator> Could not connect to engine: %v", err))
			exitChan <- true
			return
		}
		connector = &engine.RPCClientConnector{Client: client}
	}
	var err error
	medi, err = engine.NewMediator(connector, loggerDb, cdrDb, cdrStats, cfg)
	if err != nil {
		engine.Logger.Crit(fmt.Sprintf("Mediator config parsing error: %v", err))
		exitChan <- true
		return
	}
	engine.Logger.Info("Registering Mediator RPC service.")
	server.RpcRegister(&apier.MediatorV1{Medi: medi})

	close(chanDone)
}
Example #10
0
func NewProxyPubSub(addr string, attempts, reconnects int) (*ProxyPubSub, error) {
	client, err := rpcclient.NewRpcClient("tcp", addr, attempts, reconnects, utils.GOB)
	if err != nil {
		return nil, err
	}
	return &ProxyPubSub{Client: client}, nil
}
Example #11
0
func NewProxyUserService(addr string, attempts, reconnects int) (*ProxyUserService, error) {
	client, err := rpcclient.NewRpcClient("tcp", addr, attempts, reconnects, utils.GOB, nil)
	if err != nil {
		return nil, err
	}
	return &ProxyUserService{Client: client}, nil
}
Example #12
0
// Special tests involving remote server (manually set)
// The server network will be manually disconnected without TCP close
func TestRPCITRmtRpcConnPool(t *testing.T) {
	if !*testRemoteRALs {
		return
	}
	rpcPoolFirst = rpcclient.NewRpcClientPool(rpcclient.POOL_FIRST, 0)
	rpcRALRmt, err := rpcclient.NewRpcClient("tcp", "172.16.254.83:2012", 1, 1, time.Duration(1*time.Second), time.Duration(2*time.Second), rpcclient.JSON_RPC, nil)
	if err != nil {
		t.Fatal(err)
	}
	rpcPoolFirst.AddClient(rpcRALRmt)
	rpcRAL1, err = rpcclient.NewRpcClient("tcp", rpcITCfg1.RPCJSONListen, 1, 1, time.Duration(1*time.Second), time.Duration(2*time.Second), rpcclient.JSON_RPC, nil)
	if err != nil {
		t.Fatal(err)
	}
	rpcPoolFirst.AddClient(rpcRAL1)
}
Example #13
0
// Fires up a cdrc instance
func startCdrc(internalCdrSChan chan *engine.CdrServer, internalRaterChan chan *engine.Responder, cdrcCfgs map[string]*config.CdrcConfig, httpSkipTlsCheck bool,
	closeChan chan struct{}, exitChan chan bool) {
	var cdrsConn engine.Connector
	var cdrcCfg *config.CdrcConfig
	for _, cdrcCfg = range cdrcCfgs { // Take the first config out, does not matter which one
		break
	}
	if cdrcCfg.Cdrs == utils.INTERNAL {
		cdrsChan := <-internalCdrSChan // This will signal that the cdrs part is populated in internalRaterChan
		internalCdrSChan <- cdrsChan   // Put it back for other components
		resp := <-internalRaterChan
		cdrsConn = resp
		internalRaterChan <- resp
	} else {
		conn, err := rpcclient.NewRpcClient("tcp", cdrcCfg.Cdrs, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB)
		if err != nil {
			utils.Logger.Crit(fmt.Sprintf("<CDRC> Could not connect to CDRS via RPC: %v", err))
			exitChan <- true
			return
		}
		cdrsConn = &engine.RPCClientConnector{Client: conn}
	}
	cdrc, err := cdrc.NewCdrc(cdrcCfgs, httpSkipTlsCheck, cdrsConn, closeChan, cfg.DefaultTimezone)
	if err != nil {
		utils.Logger.Crit(fmt.Sprintf("Cdrc config parsing error: %s", err.Error()))
		exitChan <- true
		return
	}
	if err := cdrc.Run(); err != nil {
		utils.Logger.Crit(fmt.Sprintf("Cdrc run error: %s", err.Error()))
		exitChan <- true // If run stopped, something is bad, stop the application
	}
}
Example #14
0
func main() {
	flag.Parse()
	var err error
	var cdrsMasterRpc *rpcclient.RpcClient
	var cdrsMasterCfgPath string
	var cdrsMasterCfg *config.CGRConfig
	cdrsMasterCfgPath = path.Join(*dataDir, "conf", "samples", "cdrsreplicationmaster")
	if cdrsMasterCfg, err = config.NewCGRConfigFromFolder(cdrsMasterCfgPath); err != nil {
		log.Fatal("Got config error: ", err.Error())
	}
	cdrsMasterRpc, err = rpcclient.NewRpcClient("tcp", cdrsMasterCfg.RPCJSONListen, 1, 1, time.Duration(1*time.Second), time.Duration(2*time.Second), "json", nil)
	if err != nil {
		log.Fatal("Could not connect to rater: ", err.Error())
	}
	cdrs := make([]*engine.CDR, 0)
	for i := 0; i < 10000; i++ {
		cdr := &engine.CDR{OriginID: fmt.Sprintf("httpjsonrpc_%d", i),
			ToR: utils.VOICE, OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_PSEUDOPREPAID,
			Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
			SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC),
			Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}}
		cdrs = append(cdrs, cdr)
	}
	var reply string
	for _, cdr := range cdrs {
		if err := cdrsMasterRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
			log.Fatal("Unexpected error: ", err.Error())
		} else if reply != utils.OK {
			log.Fatal("Unexpected reply received: ", reply)
		}
	}
}
Example #15
0
func NewProxyPubSub(addr string, attempts, reconnects int, connectTimeout, replyTimeout time.Duration) (*ProxyPubSub, error) {
	client, err := rpcclient.NewRpcClient("tcp", addr, attempts, reconnects, connectTimeout, replyTimeout, utils.GOB, nil)
	if err != nil {
		return nil, err
	}
	return &ProxyPubSub{Client: client}, nil
}
Example #16
0
// Special tests involving remote server (manually set)
// The server network will be manually disconnected without TCP close
// Run remote ones with: go test -tags=integration -run="TestRPCITRmt|TestRPCITStop" -remote_rals
func TestRPCITRmtRpcConnPool(t *testing.T) {
	if !*testRemoteRALs {
		return
	}
	rpcPoolFirst = rpcclient.NewRpcClientPool(rpcclient.POOL_FIRST, 0)
	rpcRALRmt, err := rpcclient.NewRpcClient("tcp", RemoteRALsAddr1, 1, 1,
		time.Duration(1*time.Second), time.Duration(2*time.Second), rpcclient.JSON_RPC, nil, false)
	if err != nil {
		t.Fatal(err)
	}
	rpcPoolFirst.AddClient(rpcRALRmt)
	rpcRAL1, err = rpcclient.NewRpcClient("tcp", RemoteRALsAddr2, 1, 1,
		time.Duration(1*time.Second), time.Duration(2*time.Second), rpcclient.JSON_RPC, nil, false)
	if err != nil {
		t.Fatal(err)
	}
	rpcPoolFirst.AddClient(rpcRAL1)
}
Example #17
0
/*
<< .Object.Property >>

Property can be a attribute or a method both used without ()
Please also note the initial dot .

Currently there are following objects that can be used:

Account -  the account that this action is called on
Action - the action with all it's attributs
Actions - the list of actions in the current action set
Sq - StatsQueueTriggered object

We can actually use everythiong that go templates offer. You can read more here: https://golang.org/pkg/text/template/
*/
func cgrRPCAction(account *Account, sq *StatsQueueTriggered, a *Action, acs Actions) error {
	// parse template
	tmpl := template.New("extra_params")
	tmpl.Delims("<<", ">>")
	t, err := tmpl.Parse(a.ExtraParameters)
	if err != nil {
		utils.Logger.Err(fmt.Sprintf("error parsing *cgr_rpc template: %s", err.Error()))
		return err
	}
	var buf bytes.Buffer
	if err = t.Execute(&buf, struct {
		Account *Account
		Sq      *StatsQueueTriggered
		Action  *Action
		Actions Actions
	}{account, sq, a, acs}); err != nil {
		utils.Logger.Err(fmt.Sprintf("error executing *cgr_rpc template %s:", err.Error()))
		return err
	}
	processedExtraParam := buf.String()
	//utils.Logger.Info("ExtraParameters: " + parsedExtraParameters)
	req := RPCRequest{}
	if err := json.Unmarshal([]byte(processedExtraParam), &req); err != nil {
		return err
	}
	params, err := utils.GetRpcParams(req.Method)
	if err != nil {
		return err
	}
	var client rpcclient.RpcClientConnection
	if req.Address != utils.MetaInternal {
		if client, err = rpcclient.NewRpcClient("tcp", req.Address, req.Attempts, 0, config.CgrConfig().ConnectTimeout, config.CgrConfig().ReplyTimeout, req.Transport, nil); err != nil {
			return err
		}
	} else {
		client = params.Object.(rpcclient.RpcClientConnection)
	}
	in, out := params.InParam, params.OutParam
	//utils.Logger.Info("Params: " + utils.ToJSON(req.Params))
	//p, err := utils.FromMapStringInterfaceValue(req.Params, in)
	mapstructure.Decode(req.Params, in)
	if err != nil {
		utils.Logger.Info("<*cgr_rpc> err: " + err.Error())
		return err
	}
	utils.Logger.Info(fmt.Sprintf("<*cgr_rpc> calling: %s with: %s", req.Method, utils.ToJSON(in)))
	if !req.Async {
		err = client.Call(req.Method, in, out)
		utils.Logger.Info(fmt.Sprintf("<*cgr_rpc> result: %s err: %v", utils.ToJSON(out), err))
		return err
	}
	go func() {
		err := client.Call(req.Method, in, out)
		utils.Logger.Info(fmt.Sprintf("<*cgr_rpc> result: %s err: %v", utils.ToJSON(out), err))
	}()
	return nil
}
Example #18
0
func startSmGeneric(internalSMGChan chan *sessionmanager.SMGeneric, internalRaterChan, internalCDRSChan chan rpcclient.RpcClientConnection, server *utils.Server, exitChan chan bool) {
	utils.Logger.Info("Starting CGRateS SMGeneric service.")
	var ralsConns, cdrsConn *rpcclient.RpcClientPool
	if len(cfg.SmGenericConfig.RALsConns) != 0 {
		ralsConns, err = engine.NewRPCPool(rpcclient.POOL_FIRST, cfg.ConnectAttempts, cfg.Reconnects, cfg.ConnectTimeout, cfg.ReplyTimeout,
			cfg.SmGenericConfig.RALsConns, internalRaterChan, cfg.InternalTtl)
		if err != nil {
			utils.Logger.Crit(fmt.Sprintf("<SMGeneric> Could not connect to RALs: %s", err.Error()))
			exitChan <- true
			return
		}
	}
	if len(cfg.SmGenericConfig.CDRsConns) != 0 {
		cdrsConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST, cfg.ConnectAttempts, cfg.Reconnects, cfg.ConnectTimeout, cfg.ReplyTimeout,
			cfg.SmGenericConfig.CDRsConns, internalCDRSChan, cfg.InternalTtl)
		if err != nil {
			utils.Logger.Crit(fmt.Sprintf("<SMGeneric> Could not connect to RALs: %s", err.Error()))
			exitChan <- true
			return
		}
	}
	smgReplConns := make([]*sessionmanager.SMGReplicationConn, len(cfg.SmGenericConfig.SMGReplicationConns))
	for i, replConnCfg := range cfg.SmGenericConfig.SMGReplicationConns {
		if replCon, err := rpcclient.NewRpcClient("tcp", replConnCfg.Address, cfg.ConnectAttempts, cfg.Reconnects,
			cfg.ConnectTimeout, cfg.ReplyTimeout, replConnCfg.Transport[1:], nil); err != nil {
			utils.Logger.Crit(fmt.Sprintf("<SMGeneric> Could not connect to SMGReplicationConn: <%s>, error: <%s>", replConnCfg.Address, err.Error()))
			exitChan <- true
			return
		} else {
			smgReplConns[i] = &sessionmanager.SMGReplicationConn{Connection: replCon, Synchronous: replConnCfg.Synchronous}
		}
	}
	sm := sessionmanager.NewSMGeneric(cfg, ralsConns, cdrsConn, smgReplConns, cfg.DefaultTimezone)
	if err = sm.Connect(); err != nil {
		utils.Logger.Err(fmt.Sprintf("<SMGeneric> error: %s!", err))
	}
	// Pass internal connection via BiRPCClient
	internalSMGChan <- sm
	// Register RPC handler
	smgRpc := v1.NewSMGenericV1(sm)
	server.RpcRegister(smgRpc)
	// Register BiRpc handlers
	//server.BiRPCRegister(v1.NewSMGenericBiRpcV1(sm))
	smgBiRpc := v1.NewSMGenericBiRpcV1(sm)
	for method, handler := range smgBiRpc.Handlers() {
		server.BiRPCRegisterName(method, handler)
	}
}
Example #19
0
func startCDRS(internalCdrSChan chan *engine.CdrServer, logDb engine.LogStorage, cdrDb engine.CdrStorage,
	internalRaterChan chan *engine.Responder, internalPubSubSChan chan engine.PublisherSubscriber,
	internalUserSChan chan engine.UserService, internalAliaseSChan chan engine.AliasService,
	internalCdrStatSChan chan engine.StatsInterface, server *engine.Server, exitChan chan bool) {
	utils.Logger.Info("Starting CGRateS CDRS service.")
	var err error
	var client *rpcclient.RpcClient
	// Rater connection init
	var raterConn engine.Connector
	if cfg.CDRSRater == utils.INTERNAL {
		responder := <-internalRaterChan // Wait for rater to come up before start querying
		raterConn = responder
		internalRaterChan <- responder // Put back the connection since there might be other entities waiting for it
	} else if len(cfg.CDRSRater) != 0 {
		client, err = rpcclient.NewRpcClient("tcp", cfg.CDRSRater, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB)
		if err != nil {
			utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to rater: %s", err.Error()))
			exitChan <- true
			return
		}
		raterConn = &engine.RPCClientConnector{Client: client}
	}
	// Pubsub connection init
	var pubSubConn engine.PublisherSubscriber
	if cfg.CDRSPubSub == utils.INTERNAL {
		pubSubs := <-internalPubSubSChan
		pubSubConn = pubSubs
		internalPubSubSChan <- pubSubs
	} else if len(cfg.CDRSPubSub) != 0 {
		if cfg.CDRSRater == cfg.CDRSPubSub {
			pubSubConn = &engine.ProxyPubSub{Client: client}
		} else {
			client, err = rpcclient.NewRpcClient("tcp", cfg.CDRSPubSub, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB)
			if err != nil {
				utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to pubsub server: %s", err.Error()))
				exitChan <- true
				return
			}
			pubSubConn = &engine.ProxyPubSub{Client: client}
		}
	}
	// Users connection init
	var usersConn engine.UserService
	if cfg.CDRSUsers == utils.INTERNAL {
		userS := <-internalUserSChan
		usersConn = userS
		internalUserSChan <- userS
	} else if len(cfg.CDRSUsers) != 0 {
		if cfg.CDRSRater == cfg.CDRSUsers {
			usersConn = &engine.ProxyUserService{Client: client}
		} else {
			client, err = rpcclient.NewRpcClient("tcp", cfg.CDRSUsers, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB)
			if err != nil {
				utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to users server: %s", err.Error()))
				exitChan <- true
				return
			}
			usersConn = &engine.ProxyUserService{Client: client}
		}
	}
	// Aliases connection init
	var aliasesConn engine.AliasService
	if cfg.CDRSAliases == utils.INTERNAL {
		aliaseS := <-internalAliaseSChan
		aliasesConn = aliaseS
		internalAliaseSChan <- aliaseS
	} else if len(cfg.CDRSAliases) != 0 {
		if cfg.CDRSRater == cfg.CDRSAliases {
			aliasesConn = &engine.ProxyAliasService{Client: client}
		} else {
			client, err = rpcclient.NewRpcClient("tcp", cfg.CDRSAliases, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB)
			if err != nil {
				utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to aliases server: %s", err.Error()))
				exitChan <- true
				return
			}
			aliasesConn = &engine.ProxyAliasService{Client: client}
		}
	}
	// Stats connection init
	var statsConn engine.StatsInterface
	if cfg.CDRSStats == utils.INTERNAL {
		statS := <-internalCdrStatSChan
		statsConn = statS
		internalCdrStatSChan <- statS
	} else if len(cfg.CDRSStats) != 0 {
		if cfg.CDRSRater == cfg.CDRSStats {
			statsConn = &engine.ProxyStats{Client: client}
		} else {
			client, err = rpcclient.NewRpcClient("tcp", cfg.CDRSStats, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB)
			if err != nil {
				utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to stats server: %s", err.Error()))
				exitChan <- true
				return
			}
			statsConn = &engine.ProxyStats{Client: client}
		}
	}

	cdrServer, _ := engine.NewCdrServer(cfg, cdrDb, raterConn, pubSubConn, usersConn, aliasesConn, statsConn)
	utils.Logger.Info("Registering CDRS HTTP Handlers.")
	cdrServer.RegisterHanlersToServer(server)
	utils.Logger.Info("Registering CDRS RPC service.")
	cdrSrv := v1.CdrsV1{CdrSrv: cdrServer}
	server.RpcRegister(&cdrSrv)
	server.RpcRegister(&v2.CdrsV2{CdrsV1: cdrSrv})
	// Make the cdr server available for internal communication
	responder := <-internalRaterChan // Retrieve again the responder
	responder.CdrSrv = cdrServer     // Attach connection to cdrServer in responder, so it can be used later
	internalRaterChan <- responder   // Put back the connection for the rest of the system
	internalCdrSChan <- cdrServer    // Signal that cdrS is operational
}
Example #20
0
// Starts rater and reports on chan
func startRater(internalRaterChan chan *engine.Responder, cacheDoneChan chan struct{}, internalBalancerChan chan *balancer2go.Balancer, internalSchedulerChan chan *scheduler.Scheduler,
	internalCdrStatSChan chan engine.StatsInterface, internalHistorySChan chan history.Scribe,
	internalPubSubSChan chan rpcclient.RpcClientConnection, internalUserSChan chan engine.UserService, internalAliaseSChan chan engine.AliasService,
	server *utils.Server,
	ratingDb engine.RatingStorage, accountDb engine.AccountingStorage, loadDb engine.LoadStorage, cdrDb engine.CdrStorage, logDb engine.LogStorage,
	stopHandled *bool, exitChan chan bool) {
	var waitTasks []chan struct{}

	//Cache load
	cacheTaskChan := make(chan struct{})
	waitTasks = append(waitTasks, cacheTaskChan)
	go func() {
		defer close(cacheTaskChan)
		if err := ratingDb.CacheRatingAll(); err != nil {
			utils.Logger.Crit(fmt.Sprintf("Cache rating error: %s", err.Error()))
			exitChan <- true
			return
		}
		if err := accountDb.CacheAccountingPrefixes(); err != nil { // Used to cache load history
			utils.Logger.Crit(fmt.Sprintf("Cache accounting error: %s", err.Error()))
			exitChan <- true
			return
		}
		cacheDoneChan <- struct{}{}
	}()

	// Retrieve scheduler for it's API methods
	var sched *scheduler.Scheduler // Need the scheduler in APIer
	if cfg.SchedulerEnabled {
		schedTaskChan := make(chan struct{})
		waitTasks = append(waitTasks, schedTaskChan)
		go func() {
			defer close(schedTaskChan)
			select {
			case sched = <-internalSchedulerChan:
				internalSchedulerChan <- sched
			case <-time.After(cfg.InternalTtl):
				utils.Logger.Crit("<Rater>: Internal scheduler connection timeout.")
				exitChan <- true
				return
			}

		}()
	}

	// Connection to balancer
	var bal *balancer2go.Balancer
	if cfg.RaterBalancer != "" {
		balTaskChan := make(chan struct{})
		waitTasks = append(waitTasks, balTaskChan)
		go func() {
			defer close(balTaskChan)
			if cfg.RaterBalancer == utils.INTERNAL {
				select {
				case bal = <-internalBalancerChan:
					internalBalancerChan <- bal // Put it back if someone else is interested about
				case <-time.After(cfg.InternalTtl):
					utils.Logger.Crit("<Rater>: Internal balancer connection timeout.")
					exitChan <- true
					return
				}
			} else {
				go registerToBalancer(exitChan)
				go stopRaterSignalHandler(internalCdrStatSChan, exitChan)
				*stopHandled = true
			}
		}()
	}

	// Connection to CDRStats
	var cdrStats engine.StatsInterface
	if cfg.RaterCdrStats != "" {
		cdrstatTaskChan := make(chan struct{})
		waitTasks = append(waitTasks, cdrstatTaskChan)
		go func() {
			defer close(cdrstatTaskChan)
			if cfg.RaterCdrStats == utils.INTERNAL {
				select {
				case cdrStats = <-internalCdrStatSChan:
					internalCdrStatSChan <- cdrStats
				case <-time.After(cfg.InternalTtl):
					utils.Logger.Crit("<Rater>: Internal cdrstats connection timeout.")
					exitChan <- true
					return
				}
			} else if cdrStats, err = engine.NewProxyStats(cfg.RaterCdrStats, cfg.ConnectAttempts, -1); err != nil {
				utils.Logger.Crit(fmt.Sprintf("<Rater> Could not connect to cdrstats, error: %s", err.Error()))
				exitChan <- true
				return
			}
		}()
	}

	// Connection to HistoryS
	if cfg.RaterHistoryServer != "" {
		histTaskChan := make(chan struct{})
		waitTasks = append(waitTasks, histTaskChan)
		go func() {
			defer close(histTaskChan)
			var scribeServer history.Scribe
			if cfg.RaterHistoryServer == utils.INTERNAL {
				select {
				case scribeServer = <-internalHistorySChan:
					internalHistorySChan <- scribeServer
				case <-time.After(cfg.InternalTtl):
					utils.Logger.Crit("<Rater>: Internal historys connection timeout.")
					exitChan <- true
					return
				}
			} else if scribeServer, err = history.NewProxyScribe(cfg.RaterHistoryServer, cfg.ConnectAttempts, -1); err != nil {
				utils.Logger.Crit(fmt.Sprintf("<Rater> Could not connect historys, error: %s", err.Error()))
				exitChan <- true
				return
			}
			engine.SetHistoryScribe(scribeServer) // ToDo: replace package sharing with connection based one
		}()
	}

	// Connection to pubsubs
	if cfg.RaterPubSubServer != "" {
		pubsubTaskChan := make(chan struct{})
		waitTasks = append(waitTasks, pubsubTaskChan)
		go func() {
			defer close(pubsubTaskChan)
			var pubSubServer rpcclient.RpcClientConnection
			if cfg.RaterPubSubServer == utils.INTERNAL {
				select {
				case pubSubServer = <-internalPubSubSChan:
					internalPubSubSChan <- pubSubServer
				case <-time.After(cfg.InternalTtl):
					utils.Logger.Crit("<Rater>: Internal pubsub connection timeout.")
					exitChan <- true
					return
				}
			} else if pubSubServer, err = rpcclient.NewRpcClient("tcp", cfg.RaterPubSubServer, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB, nil); err != nil {
				utils.Logger.Crit(fmt.Sprintf("<Rater> Could not connect to pubsubs: %s", err.Error()))
				exitChan <- true
				return
			}
			engine.SetPubSub(pubSubServer) // ToDo: replace package sharing with connection based one
		}()
	}

	// Connection to AliasService
	if cfg.RaterAliasesServer != "" {
		aliasesTaskChan := make(chan struct{})
		waitTasks = append(waitTasks, aliasesTaskChan)
		go func() {
			defer close(aliasesTaskChan)
			var aliasesServer engine.AliasService
			if cfg.RaterAliasesServer == utils.INTERNAL {
				select {
				case aliasesServer = <-internalAliaseSChan:
					internalAliaseSChan <- aliasesServer
				case <-time.After(cfg.InternalTtl):
					utils.Logger.Crit("<Rater>: Internal aliases connection timeout.")
					exitChan <- true
					return
				}
			} else if aliasesServer, err = engine.NewProxyAliasService(cfg.RaterAliasesServer, cfg.ConnectAttempts, -1); err != nil {
				utils.Logger.Crit(fmt.Sprintf("<Rater> Could not connect to aliases, error: %s", err.Error()))
				exitChan <- true
				return
			}
			engine.SetAliasService(aliasesServer) // ToDo: replace package sharing with connection based one
		}()
	}

	// Connection to UserService
	var userServer engine.UserService
	if cfg.RaterUserServer != "" {
		usersTaskChan := make(chan struct{})
		waitTasks = append(waitTasks, usersTaskChan)
		go func() {
			defer close(usersTaskChan)
			if cfg.RaterUserServer == utils.INTERNAL {
				select {
				case userServer = <-internalUserSChan:
					internalUserSChan <- userServer
				case <-time.After(cfg.InternalTtl):
					utils.Logger.Crit("<Rater>: Internal users connection timeout.")
					exitChan <- true
					return
				}
			} else if userServer, err = engine.NewProxyUserService(cfg.RaterUserServer, cfg.ConnectAttempts, -1); err != nil {
				utils.Logger.Crit(fmt.Sprintf("<Rater> Could not connect users, error: %s", err.Error()))
				exitChan <- true
				return
			}
			engine.SetUserService(userServer)
		}()
	}

	// Wait for all connections to complete before going further
	for _, chn := range waitTasks {
		<-chn
	}

	responder := &engine.Responder{Bal: bal, ExitChan: exitChan, Stats: cdrStats}
	apierRpcV1 := &v1.ApierV1{StorDb: loadDb, RatingDb: ratingDb, AccountDb: accountDb, CdrDb: cdrDb, LogDb: logDb, Sched: sched,
		Config: cfg, Responder: responder, CdrStatsSrv: cdrStats, Users: userServer}
	apierRpcV2 := &v2.ApierV2{
		ApierV1: *apierRpcV1}
	// internalSchedulerChan shared here
	server.RpcRegister(responder)
	server.RpcRegister(apierRpcV1)
	server.RpcRegister(apierRpcV2)
	internalRaterChan <- responder // Rater done
}
Example #21
0
func main() {
	flag.Parse()
	if *version {
		fmt.Println("CGRateS " + utils.VERSION)
		return
	}
	var err error
	client, err = rpcclient.NewRpcClient("tcp", *server, 3, 3, time.Duration(1*time.Second), time.Duration(5*time.Minute), *rpc_encoding, nil)
	if err != nil {
		flag.PrintDefaults()
		log.Fatal("Could not connect to server " + *server)
	}

	if len(flag.Args()) != 0 {
		executeCommand(strings.Join(flag.Args(), " "))
		return
	}

	fmt.Println("Welcome to CGRateS console!")
	fmt.Print("Type `help` for a list of commands\n\n")

	line := liner.NewLiner()
	defer line.Close()

	line.SetCompleter(func(line string) (comp []string) {
		commands := console.GetCommands()
		for name, cmd := range commands {
			if strings.HasPrefix(name, strings.ToLower(line)) {
				comp = append(comp, name)
			}
			// try arguments
			if strings.HasPrefix(line, name) {
				// get last word
				lastSpace := strings.LastIndex(line, " ")
				lastSpace += 1
				for _, arg := range cmd.ClientArgs() {
					if strings.HasPrefix(arg, line[lastSpace:]) {
						comp = append(comp, line[:lastSpace]+arg)
					}
				}
			}
		}
		return
	})

	if f, err := os.Open(history_fn); err == nil {
		line.ReadHistory(f)
		f.Close()
	}

	stop := false
	for !stop {
		if command, err := line.Prompt("cgr> "); err != nil {
			if err == io.EOF {
				fmt.Println("\nbye!")
				stop = true
			} else {
				fmt.Print("Error reading line: ", err)
			}
		} else {
			line.AppendHistory(command)
			switch strings.ToLower(strings.TrimSpace(command)) {
			case "quit", "exit", "bye", "close":
				fmt.Println("\nbye!")
				stop = true
			default:
				executeCommand(command)
			}
		}
	}

	if f, err := os.Create(history_fn); err != nil {
		log.Print("Error writing history file: ", err)
	} else {
		line.WriteHistory(f)
		f.Close()
	}
}
Example #22
0
func main() {
	flag.Parse()
	if *version {
		fmt.Println("CGRateS " + utils.VERSION)
		return
	}
	var errRatingDb, errAccDb, errStorDb, err error
	var ratingDb engine.RatingStorage
	var accountDb engine.AccountingStorage
	var storDb engine.LoadStorage
	var rater, cdrstats, users *rpc.Client
	var loader engine.LoadReader
	if *migrateRC8 != "" {
		if *datadb_type == "redis" && *tpdb_type == "redis" {
			var db_nb int
			db_nb, err = strconv.Atoi(*datadb_name)
			if err != nil {
				log.Print("Redis db name must be an integer!")
				return
			}
			host := *datadb_host
			if *datadb_port != "" {
				host += ":" + *datadb_port
			}
			migratorRC8acc, err := NewMigratorRC8(host, db_nb, *datadb_pass, *dbdata_encoding)
			if err != nil {
				log.Print(err.Error())
				return
			}
			if strings.Contains(*migrateRC8, "acc") || strings.Contains(*migrateRC8, "*all") {
				if err := migratorRC8acc.migrateAccounts(); err != nil {
					log.Print(err.Error())
				}
			}

			db_nb, err = strconv.Atoi(*tpdb_name)
			if err != nil {
				log.Print("Redis db name must be an integer!")
				return
			}
			host = *tpdb_host
			if *tpdb_port != "" {
				host += ":" + *tpdb_port
			}
			migratorRC8rat, err := NewMigratorRC8(host, db_nb, *tpdb_pass, *dbdata_encoding)
			if err != nil {
				log.Print(err.Error())
				return
			}
			if strings.Contains(*migrateRC8, "atr") || strings.Contains(*migrateRC8, "*all") {
				if err := migratorRC8rat.migrateActionTriggers(); err != nil {
					log.Print(err.Error())
				}
			}
			if strings.Contains(*migrateRC8, "act") || strings.Contains(*migrateRC8, "*all") {
				if err := migratorRC8rat.migrateActions(); err != nil {
					log.Print(err.Error())
				}
			}
			if strings.Contains(*migrateRC8, "dcs") || strings.Contains(*migrateRC8, "*all") {
				if err := migratorRC8rat.migrateDerivedChargers(); err != nil {
					log.Print(err.Error())
				}
			}
			if strings.Contains(*migrateRC8, "apl") || strings.Contains(*migrateRC8, "*all") {
				if err := migratorRC8rat.migrateActionPlans(); err != nil {
					log.Print(err.Error())
				}
			}
			if strings.Contains(*migrateRC8, "shg") || strings.Contains(*migrateRC8, "*all") {
				if err := migratorRC8rat.migrateSharedGroups(); err != nil {
					log.Print(err.Error())
				}
			}
			if strings.Contains(*migrateRC8, "int") {
				if err := migratorRC8acc.migrateAccountsInt(); err != nil {
					log.Print(err.Error())
				}
				if err := migratorRC8rat.migrateActionTriggersInt(); err != nil {
					log.Print(err.Error())
				}
				if err := migratorRC8rat.migrateActionsInt(); err != nil {
					log.Print(err.Error())
				}
			}
			if strings.Contains(*migrateRC8, "vf") {
				if err := migratorRC8rat.migrateActionsInt2(); err != nil {
					log.Print(err.Error())
				}
				if err := migratorRC8acc.writeVersion(); err != nil {
					log.Print(err.Error())
				}
			}
		} else if *datadb_type == "mongo" && *tpdb_type == "mongo" {
			mongoMigratorAcc, err := NewMongoMigrator(*datadb_host, *datadb_port, *datadb_name, *datadb_user, *datadb_pass)
			if err != nil {
				log.Print(err.Error())
				return
			}
			mongoMigratorRat, err := NewMongoMigrator(*tpdb_host, *tpdb_port, *tpdb_name, *tpdb_user, *tpdb_pass)
			if err != nil {
				log.Print(err.Error())
				return
			}
			if strings.Contains(*migrateRC8, "vf") {
				if err := mongoMigratorRat.migrateActions(); err != nil {
					log.Print(err.Error())
				}
				if err := mongoMigratorAcc.writeVersion(); err != nil {
					log.Print(err.Error())
				}
			}
		}

		log.Print("Done!")
		return
	}
	// Init necessary db connections, only if not already
	if !*dryRun { // make sure we do not need db connections on dry run, also not importing into any stordb
		if *fromStorDb {
			ratingDb, errRatingDb = engine.ConfigureRatingStorage(*tpdb_type, *tpdb_host, *tpdb_port, *tpdb_name,
				*tpdb_user, *tpdb_pass, *dbdata_encoding, cgrConfig.CacheConfig, *loadHistorySize)
			accountDb, errAccDb = engine.ConfigureAccountingStorage(*datadb_type, *datadb_host, *datadb_port, *datadb_name, *datadb_user, *datadb_pass, *dbdata_encoding, cgrConfig.CacheConfig, *loadHistorySize)
			storDb, errStorDb = engine.ConfigureLoadStorage(*stor_db_type, *stor_db_host, *stor_db_port, *stor_db_name, *stor_db_user, *stor_db_pass, *dbdata_encoding,
				cgrConfig.StorDBMaxOpenConns, cgrConfig.StorDBMaxIdleConns, cgrConfig.StorDBCDRSIndexes)
		} else if *toStorDb { // Import from csv files to storDb
			storDb, errStorDb = engine.ConfigureLoadStorage(*stor_db_type, *stor_db_host, *stor_db_port, *stor_db_name, *stor_db_user, *stor_db_pass, *dbdata_encoding,
				cgrConfig.StorDBMaxOpenConns, cgrConfig.StorDBMaxIdleConns, cgrConfig.StorDBCDRSIndexes)
		} else { // Default load from csv files to dataDb
			ratingDb, errRatingDb = engine.ConfigureRatingStorage(*tpdb_type, *tpdb_host, *tpdb_port, *tpdb_name,
				*tpdb_user, *tpdb_pass, *dbdata_encoding, cgrConfig.CacheConfig, *loadHistorySize)
			accountDb, errAccDb = engine.ConfigureAccountingStorage(*datadb_type, *datadb_host, *datadb_port, *datadb_name, *datadb_user, *datadb_pass, *dbdata_encoding, cgrConfig.CacheConfig, *loadHistorySize)
		}
		// Defer databases opened to be closed when we are done
		for _, db := range []engine.Storage{ratingDb, accountDb, storDb} {
			if db != nil {
				defer db.Close()
			}
		}
		// Stop on db errors
		for _, err = range []error{errRatingDb, errAccDb, errStorDb} {
			if err != nil {
				log.Fatalf("Could not open database connection: %v", err)
			}
		}
		if *toStorDb { // Import files from a directory into storDb
			if *tpid == "" {
				log.Fatal("TPid required, please define it via *-tpid* command argument.")
			}
			csvImporter := engine.TPCSVImporter{
				TPid:     *tpid,
				StorDb:   storDb,
				DirPath:  *dataPath,
				Sep:      ',',
				Verbose:  *verbose,
				ImportId: *runId,
			}
			if errImport := csvImporter.Run(); errImport != nil {
				log.Fatal(errImport)
			}
			return
		}
	}
	if *fromStorDb { // Load Tariff Plan from storDb into dataDb
		loader = storDb
	} else { // Default load from csv files to dataDb
		/*for fn, v := range engine.FileValidators {
			err := engine.ValidateCSVData(path.Join(*dataPath, fn), v.Rule)
			if err != nil {
				log.Fatal(err, "\n\t", v.Message)
			}
		}*/
		loader = engine.NewFileCSVStorage(',',
			path.Join(*dataPath, utils.DESTINATIONS_CSV),
			path.Join(*dataPath, utils.TIMINGS_CSV),
			path.Join(*dataPath, utils.RATES_CSV),
			path.Join(*dataPath, utils.DESTINATION_RATES_CSV),
			path.Join(*dataPath, utils.RATING_PLANS_CSV),
			path.Join(*dataPath, utils.RATING_PROFILES_CSV),
			path.Join(*dataPath, utils.SHARED_GROUPS_CSV),
			path.Join(*dataPath, utils.LCRS_CSV),
			path.Join(*dataPath, utils.ACTIONS_CSV),
			path.Join(*dataPath, utils.ACTION_PLANS_CSV),
			path.Join(*dataPath, utils.ACTION_TRIGGERS_CSV),
			path.Join(*dataPath, utils.ACCOUNT_ACTIONS_CSV),
			path.Join(*dataPath, utils.DERIVED_CHARGERS_CSV),
			path.Join(*dataPath, utils.CDR_STATS_CSV),
			path.Join(*dataPath, utils.USERS_CSV),
			path.Join(*dataPath, utils.ALIASES_CSV),
			path.Join(*dataPath, utils.ResourceLimitsCsv),
		)
	}
	tpReader := engine.NewTpReader(ratingDb, accountDb, loader, *tpid, *timezone)
	err = tpReader.LoadAll()
	if err != nil {
		log.Fatal(err)
	}
	if *stats {
		tpReader.ShowStatistics()
	}
	if *validate {
		if !tpReader.IsValid() {
			return
		}
	}
	if *dryRun { // We were just asked to parse the data, not saving it
		return
	}
	if *historyServer != "" { // Init scribeAgent so we can store the differences
		if scribeAgent, err := rpcclient.NewRpcClient("tcp", *historyServer, 3, 3, time.Duration(1*time.Second), time.Duration(5*time.Minute), utils.GOB, nil); err != nil {
			log.Fatalf("Could not connect to history server, error: %s. Make sure you have properly configured it via -history_server flag.", err.Error())
			return
		} else {
			engine.SetHistoryScribe(scribeAgent)
			//defer scribeAgent.Client.Close()
		}
	} else {
		log.Print("WARNING: Rates history archiving is disabled!")
	}
	if *raterAddress != "" { // Init connection to rater so we can reload it's data
		rater, err = rpc.Dial("tcp", *raterAddress)
		if err != nil {
			log.Fatalf("Could not connect to rater: %s", err.Error())
			return
		}
	} else {
		log.Print("WARNING: Rates automatic cache reloading is disabled!")
	}
	if *cdrstatsAddress != "" { // Init connection to rater so we can reload it's data
		if *cdrstatsAddress == *raterAddress {
			cdrstats = rater
		} else {
			cdrstats, err = rpc.Dial("tcp", *cdrstatsAddress)
			if err != nil {
				log.Fatalf("Could not connect to CDRStats API: %s", err.Error())
				return
			}
		}
	} else {
		log.Print("WARNING: CDRStats automatic data reload is disabled!")
	}
	if *usersAddress != "" { // Init connection to rater so we can reload it's data
		if *usersAddress == *raterAddress {
			users = rater
		} else {
			users, err = rpc.Dial("tcp", *usersAddress)
			if err != nil {
				log.Fatalf("Could not connect to Users API: %s", err.Error())
				return
			}
		}
	} else {
		log.Print("WARNING: Users automatic data reload is disabled!")
	}

	// write maps to database
	if err := tpReader.WriteToDatabase(*flush, *verbose, *disable_reverse); err != nil {
		log.Fatal("Could not write to database: ", err)
	}
	if len(*historyServer) != 0 && *verbose {
		log.Print("Wrote history.")
	}
	var dstIds, rplIds, rpfIds, actIds, shgIds, alsIds, lcrIds, dcsIds, rlIDs []string
	if rater != nil {
		dstIds, _ = tpReader.GetLoadedIds(utils.DESTINATION_PREFIX)
		rplIds, _ = tpReader.GetLoadedIds(utils.RATING_PLAN_PREFIX)
		rpfIds, _ = tpReader.GetLoadedIds(utils.RATING_PROFILE_PREFIX)
		actIds, _ = tpReader.GetLoadedIds(utils.ACTION_PREFIX)
		shgIds, _ = tpReader.GetLoadedIds(utils.SHARED_GROUP_PREFIX)
		alsIds, _ = tpReader.GetLoadedIds(utils.ALIASES_PREFIX)
		lcrIds, _ = tpReader.GetLoadedIds(utils.LCR_PREFIX)
		dcsIds, _ = tpReader.GetLoadedIds(utils.DERIVEDCHARGERS_PREFIX)
		rlIDs, _ = tpReader.GetLoadedIds(utils.ResourceLimitsPrefix)
	}
	actTmgIds, _ := tpReader.GetLoadedIds(utils.ACTION_PLAN_PREFIX)
	var statsQueueIds []string
	if cdrstats != nil {
		statsQueueIds, _ = tpReader.GetLoadedIds(utils.CDR_STATS_PREFIX)
	}
	var userIds []string
	if users != nil {
		userIds, _ = tpReader.GetLoadedIds(utils.USERS_PREFIX)
	}
	// release the reader with it's structures
	tpReader.Init()

	// Reload scheduler and cache
	if rater != nil {
		reply := ""

		// Reload cache first since actions could be calling info from within
		if *verbose {
			log.Print("Reloading cache")
		}
		if *flush {
			dstIds, rplIds, rpfIds, lcrIds = nil, nil, nil, nil // Should reload all these on flush
		}
		if err = rater.Call("ApierV1.ReloadCache", utils.AttrReloadCache{
			DestinationIds:   &dstIds,
			RatingPlanIds:    &rplIds,
			RatingProfileIds: &rpfIds,
			ActionIds:        &actIds,
			SharedGroupIds:   &shgIds,
			Aliases:          &alsIds,
			LCRIds:           &lcrIds,
			DerivedChargers:  &dcsIds,
			ResourceLimits:   &rlIDs,
		}, &reply); err != nil {
			log.Printf("WARNING: Got error on cache reload: %s\n", err.Error())
		}

		if len(actTmgIds) != 0 {
			if *verbose {
				log.Print("Reloading scheduler")
			}
			if err = rater.Call("ApierV1.ReloadScheduler", "", &reply); err != nil {
				log.Printf("WARNING: Got error on scheduler reload: %s\n", err.Error())
			}
		}

	}
	if cdrstats != nil {
		if *flush {
			statsQueueIds = []string{} // Force reload all
		}
		if len(statsQueueIds) != 0 {
			if *verbose {
				log.Print("Reloading CDRStats data")
			}
			var reply string
			if err := cdrstats.Call("CDRStatsV1.ReloadQueues", utils.AttrCDRStatsReloadQueues{StatsQueueIds: statsQueueIds}, &reply); err != nil {
				log.Printf("WARNING: Failed reloading stat queues, error: %s\n", err.Error())
			}
		}
	}

	if users != nil {
		if len(userIds) > 0 {
			if *verbose {
				log.Print("Reloading Users data")
			}
			var reply string
			if err := cdrstats.Call("UsersV1.ReloadUsers", "", &reply); err != nil {
				log.Printf("WARNING: Failed reloading users data, error: %s\n", err.Error())
			}

		}
	}
}