From 95565e8ff088fb8ccacdb735f4c127c82894d822 Mon Sep 17 00:00:00 2001 From: DanB Date: Fri, 15 Sep 2017 11:55:50 +0200 Subject: [PATCH 1/3] Loader to consider tenant when building up resource indexes --- data/tariffplans/tutorial/Resources.csv | 14 ++-- engine/loader_csv_test.go | 78 ++++++++++---------- engine/resources.go | 5 ++ engine/tp_reader.go | 98 ++++++++++++++----------- utils/coreutils.go | 20 +++++ 5 files changed, 126 insertions(+), 89 deletions(-) diff --git a/data/tariffplans/tutorial/Resources.csv b/data/tariffplans/tutorial/Resources.csv index 30f655dcc..e67f01a71 100755 --- a/data/tariffplans/tutorial/Resources.csv +++ b/data/tariffplans/tutorial/Resources.csv @@ -1,8 +1,8 @@ #Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],TTL[6],Limit[7],AllocationMessage[8],Blocker[9],Stored[10],Weight[11],Thresholds[12] -Tester,ResGroup1,*string,Account,1001;1002,2014-07-29T15:00:00Z,1s,7,,true,true,20, -Tester,ResGroup1,*string_prefix,Destination,10;20,,,,,,,, -Tester,ResGroup1,*rsr_fields,,Subject(~^1.*1$);Destination(1002),,,,,,,, -Tester,ResGroup2,*destinations,Destination,DST_FS,2014-07-29T15:00:00Z,3600s,8,SPECIAL_1002,true,true,10, -Tester,ResGroup3,*string,Account,3001,2014-07-29T15:00:00Z,1s,3,,true,true,20, -#ResGroup3,*timings,SetupTime,PEAK,,,,,,,, -#ResGroup3,*cdr_stats,,CDRST1:*min_ASR:34;CDRST_1001:*min_ASR:20,,,,,,,, +cgrates.org,ResGroup1,*string,Account,1001;1002,2014-07-29T15:00:00Z,1s,7,,true,true,20, +cgrates.org,ResGroup1,*string_prefix,Destination,10;20,,,,,,,, +cgrates.org,ResGroup1,*rsr_fields,,Subject(~^1.*1$);Destination(1002),,,,,,,, +cgrates.org,ResGroup2,*destinations,Destination,DST_FS,2014-07-29T15:00:00Z,3600s,8,SPECIAL_1002,true,true,10, +cgrates.org,ResGroup3,*string,Account,3001,2014-07-29T15:00:00Z,1s,3,,true,true,20, +#cgrates.org,ResGroup3,*timings,SetupTime,PEAK,,,,,,,, +#cgrates.org,ResGroup3,*cdr_stats,,CDRST1:*min_ASR:34;CDRST_1001:*min_ASR:20,,,,,,,, diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 0ff3b6eee..39c0c3823 100755 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -267,10 +267,10 @@ cgrates.org,mas,true,another,value,10 ` resProfiles = ` #Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],TTL[6],Limit[7],AllocationMessage[8],Blocker[9],Stored[10],Weight[11],Thresholds[12] -Tester,ResGroup21,*string,HdrAccount,1001;1002,2014-07-29T15:00:00Z,1s,2,call,true,true,10, -Tester,ResGroup21,*string_prefix,HdrDestination,10;20,,,,,,,, -Tester,ResGroup21,*rsr_fields,,HdrSubject(~^1.*1$);HdrDestination(1002),,,,,,,, -Tester,ResGroup22,*destinations,HdrDestination,DST_FS,2014-07-29T15:00:00Z,3600s,2,premium_call,true,true,10, +cgrates.org,ResGroup21,*string,HdrAccount,1001;1002,2014-07-29T15:00:00Z,1s,2,call,true,true,10, +cgrates.org,ResGroup21,*string_prefix,HdrDestination,10;20,,,,,,,, +cgrates.org,ResGroup21,*rsr_fields,,HdrSubject(~^1.*1$);HdrDestination(1002),,,,,,,, +cgrates.org,ResGroup22,*destinations,HdrDestination,DST_FS,2014-07-29T15:00:00Z,3600s,2,premium_call,true,true,10, ` stats = ` #Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],QueueLength[6],TTL[7],Metrics[8],Blocker[9],Stored[10],Weight[11],Thresholds[12] @@ -1390,44 +1390,46 @@ func TestLoadReverseAliases(t *testing.T) { } func TestLoadResourceProfiles(t *testing.T) { - eResProfiles := map[string]*utils.TPResource{ - "ResGroup21": &utils.TPResource{ - TPid: testTPID, - Tenant: "Tester", - ID: "ResGroup21", - Filters: []*utils.TPRequestFilter{ - &utils.TPRequestFilter{Type: MetaString, FieldName: "HdrAccount", Values: []string{"1001", "1002"}}, - &utils.TPRequestFilter{Type: MetaStringPrefix, FieldName: "HdrDestination", Values: []string{"10", "20"}}, - &utils.TPRequestFilter{Type: MetaRSRFields, Values: []string{"HdrSubject(~^1.*1$)", "HdrDestination(1002)"}}, + eResProfiles := map[string]map[string]*utils.TPResource{ + "cgrates.org": map[string]*utils.TPResource{ + "ResGroup21": &utils.TPResource{ + TPid: testTPID, + Tenant: "cgrates.org", + ID: "ResGroup21", + Filters: []*utils.TPRequestFilter{ + &utils.TPRequestFilter{Type: MetaString, FieldName: "HdrAccount", Values: []string{"1001", "1002"}}, + &utils.TPRequestFilter{Type: MetaStringPrefix, FieldName: "HdrDestination", Values: []string{"10", "20"}}, + &utils.TPRequestFilter{Type: MetaRSRFields, Values: []string{"HdrSubject(~^1.*1$)", "HdrDestination(1002)"}}, + }, + ActivationInterval: &utils.TPActivationInterval{ + ActivationTime: "2014-07-29T15:00:00Z", + }, + UsageTTL: "1s", + AllocationMessage: "call", + Weight: 10, + Limit: "2", }, - ActivationInterval: &utils.TPActivationInterval{ - ActivationTime: "2014-07-29T15:00:00Z", + "ResGroup22": &utils.TPResource{ + TPid: testTPID, + Tenant: "cgrates.org", + ID: "ResGroup22", + Filters: []*utils.TPRequestFilter{ + &utils.TPRequestFilter{Type: MetaDestinations, FieldName: "HdrDestination", Values: []string{"DST_FS"}}, + }, + ActivationInterval: &utils.TPActivationInterval{ + ActivationTime: "2014-07-29T15:00:00Z", + }, + UsageTTL: "3600s", + AllocationMessage: "premium_call", + Blocker: true, + Stored: true, + Weight: 10, + Limit: "2", }, - UsageTTL: "1s", - AllocationMessage: "call", - Weight: 10, - Limit: "2", - }, - "ResGroup22": &utils.TPResource{ - TPid: testTPID, - Tenant: "Tester", - ID: "ResGroup22", - Filters: []*utils.TPRequestFilter{ - &utils.TPRequestFilter{Type: MetaDestinations, FieldName: "HdrDestination", Values: []string{"DST_FS"}}, - }, - ActivationInterval: &utils.TPActivationInterval{ - ActivationTime: "2014-07-29T15:00:00Z", - }, - UsageTTL: "3600s", - AllocationMessage: "premium_call", - Blocker: true, - Stored: true, - Weight: 10, - Limit: "2", }, } - if len(csvr.resProfiles) != len(eResProfiles) { - t.Error("Failed to load resourceProfiles: ", len(csvr.resProfiles)) + if len(csvr.resProfiles["cgrates.org"]) != len(eResProfiles["cgrates.org"]) { + t.Errorf("Failed to load resourceProfiles: %s", utils.ToIJSON(csvr.resProfiles)) } else if !reflect.DeepEqual(eResProfiles["ResGroup22"], csvr.resProfiles["ResGroup22"]) { t.Errorf("Expecting: %+v, received: %+v", eResProfiles["ResGroup22"], csvr.resProfiles["ResGroup22"]) diff --git a/engine/resources.go b/engine/resources.go index 40a2c5ba7..5936ba07e 100755 --- a/engine/resources.go +++ b/engine/resources.go @@ -52,6 +52,11 @@ type ResourceProfile struct { Thresholds []string // Thresholds to check after changing Limit } +// TenantID returns unique identifier of the ResourceProfile in a multi-tenant environment +func (rp *ResourceProfile) TenantID() string { + return utils.ConcatenatedKey(rp.Tenant, rp.ID) +} + // ResourceUsage represents an usage counted type ResourceUsage struct { Tenant string diff --git a/engine/tp_reader.go b/engine/tp_reader.go index d1959c0de..62d509641 100755 --- a/engine/tp_reader.go +++ b/engine/tp_reader.go @@ -53,11 +53,11 @@ type TpReader struct { cdrStats map[string]*CdrStats users map[string]*UserProfile aliases map[string]*Alias - resProfiles map[string]*utils.TPResource + resProfiles map[string]map[string]*utils.TPResource sqProfiles map[string]*utils.TPStats thresholds map[string]*utils.TPThreshold - resources []string // IDs of resources which need creation based on resourceProfiles - statQueues []string // IDs of statQueues which need creation based on statQueueProfiles + resources []*utils.TenantID // IDs of resources which need creation based on resourceProfiles + statQueues []string // IDs of statQueues which need creation based on statQueueProfiles revDests, revAliases, @@ -129,7 +129,7 @@ func (tpr *TpReader) Init() { tpr.users = make(map[string]*UserProfile) tpr.aliases = make(map[string]*Alias) tpr.derivedChargers = make(map[string]*utils.DerivedChargers) - tpr.resProfiles = make(map[string]*utils.TPResource) + tpr.resProfiles = make(map[string]map[string]*utils.TPResource) tpr.sqProfiles = make(map[string]*utils.TPStats) tpr.thresholds = make(map[string]*utils.TPThreshold) tpr.revDests = make(map[string][]string) @@ -1599,16 +1599,22 @@ func (tpr *TpReader) LoadResourceProfilesFiltered(tag string) error { if err != nil { return err } - mapRsPs := make(map[string]*utils.TPResource) + mapRsPfls := make(map[string]map[string]*utils.TPResource) for _, rl := range rls { - mapRsPs[rl.ID] = rl + if _, has := mapRsPfls[rl.Tenant]; !has { + mapRsPfls[rl.Tenant] = make(map[string]*utils.TPResource) + } + mapRsPfls[rl.Tenant][rl.ID] = rl } - tpr.resProfiles = mapRsPs - for rID := range mapRsPs { - if has, err := tpr.dataStorage.HasData(utils.ResourcesPrefix, rID); err != nil { - return err - } else if !has { - tpr.resources = append(tpr.resources, rID) + tpr.resProfiles = mapRsPfls + for tenant, mpID := range mapRsPfls { + for id := range mpID { + rTid := &utils.TenantID{tenant, id} + if has, err := tpr.dataStorage.HasData(utils.ResourcesPrefix, rTid.TenantID()); err != nil { + return err + } else if !has { + tpr.resources = append(tpr.resources, rTid) + } } } return nil @@ -1952,27 +1958,29 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err if verbose { log.Print("ResourceProfiles:") } - for _, tpRsp := range tpr.resProfiles { - rsp, err := APItoResource(tpRsp, tpr.timezone) - if err != nil { - return err - } - if err = tpr.dataStorage.SetResourceProfile(rsp, utils.NonTransactional); err != nil { - return err - } - if verbose { - log.Print("\t", rsp.ID) + for _, mpID := range tpr.resProfiles { + for _, tpRsp := range mpID { + rsp, err := APItoResource(tpRsp, tpr.timezone) + if err != nil { + return err + } + if err = tpr.dataStorage.SetResourceProfile(rsp, utils.NonTransactional); err != nil { + return err + } + if verbose { + log.Print("\t", rsp.TenantID()) + } } } if verbose { log.Print("Resources:") } - for _, rID := range tpr.resources { - if err = tpr.dataStorage.SetResource(&Resource{ID: rID, Usages: make(map[string]*ResourceUsage)}); err != nil { + for _, rTid := range tpr.resources { + if err = tpr.dataStorage.SetResource(&Resource{Tenant: rTid.Tenant, ID: rTid.ID, Usages: make(map[string]*ResourceUsage)}); err != nil { return } if verbose { - log.Print("\t", rID) + log.Print("\t", rTid.TenantID()) } } if verbose { @@ -2057,22 +2065,24 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err if verbose { log.Print("Indexing resource profiles") } - rlIdxr, err := NewReqFilterIndexer(tpr.dataStorage, utils.ResourceProfilesIndex) - if err != nil { - return err - } - for _, tpRL := range tpr.resProfiles { - if rl, err := APItoResource(tpRL, tpr.timezone); err != nil { + for tenant, mpID := range tpr.resProfiles { + rlIdxr, err := NewReqFilterIndexer(tpr.dataStorage, utils.ResourceProfilesIndex+tenant) + if err != nil { + return err + } + for _, tpRL := range mpID { + if rl, err := APItoResource(tpRL, tpr.timezone); err != nil { + return err + } else { + rlIdxr.IndexFilters(rl.ID, rl.Filters) + } + } + if verbose { + log.Printf("Indexed ResourceProfile tenant: %s keys: %+v", tenant, rlIdxr.ChangedKeys().Slice()) + } + if err := rlIdxr.StoreIndexes(); err != nil { return err - } else { - rlIdxr.IndexFilters(rl.ID, rl.Filters) } - } - if verbose { - log.Printf("Indexed ResourceProfile keys: %+v", rlIdxr.ChangedKeys().Slice()) - } - if err := rlIdxr.StoreIndexes(); err != nil { - return err } } if len(tpr.sqProfiles) > 0 { @@ -2294,11 +2304,11 @@ func (tpr *TpReader) GetLoadedIds(categ string) ([]string, error) { } return keys, nil case utils.ResourceProfilesPrefix: - keys := make([]string, len(tpr.resProfiles)) - i := 0 - for k := range tpr.resProfiles { - keys[i] = k - i++ + keys := make([]string, 0) + for tenant, mpID := range tpr.resProfiles { + for id := range mpID { + keys = append(keys, utils.ConcatenatedKey(tenant, id)) + } } return keys, nil case utils.ACTION_TRIGGER_PREFIX: diff --git a/utils/coreutils.go b/utils/coreutils.go index 7f0240d7f..df8db9ec3 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -759,3 +759,23 @@ func AppendToFile(fName, text string) error { f.Close() return nil } + +func NewTenantID(tntID string) *TenantID { + if strings.Index(tntID, CONCATENATED_KEY_SEP) == -1 { // no :, ID without Tenant + return &TenantID{ID: tntID} + } + tIDSplt := strings.Split(tntID, CONCATENATED_KEY_SEP) + if len(tIDSplt) == 1 { // only Tenant present + return &TenantID{Tenant: tIDSplt[0]} + } + return &TenantID{Tenant: tIDSplt[0], ID: tIDSplt[1]} +} + +type TenantID struct { + Tenant string + ID string +} + +func (tID *TenantID) TenantID() string { + return ConcatenatedKey(tID.Tenant, tID.ID) +} From 9fbe0eefa4c85ee9f936ffc3533bf98200ccf945 Mon Sep 17 00:00:00 2001 From: DanB Date: Fri, 15 Sep 2017 14:18:56 +0200 Subject: [PATCH 2/3] Tenant in Resource --- apier/v1/resourcesv1.go | 23 ++++++++-------- engine/resources.go | 49 +++++++++++++++++++++++----------- engine/storage_interface.go | 8 +++--- engine/storage_map.go | 27 ++++++++++--------- engine/storage_mongo_datadb.go | 36 ++++++++++++++----------- engine/storage_redis.go | 26 +++++++++--------- 6 files changed, 98 insertions(+), 71 deletions(-) diff --git a/apier/v1/resourcesv1.go b/apier/v1/resourcesv1.go index 812ae545c..1bb3d5880 100644 --- a/apier/v1/resourcesv1.go +++ b/apier/v1/resourcesv1.go @@ -81,16 +81,17 @@ func (rsv1 *ResourceSV1) ReleaseResource(args utils.AttrRLsResourceUsage, reply return rsv1.rls.V1ReleaseResource(args, reply) } -type AttrGetResPrf struct { - ID string +type ArgGetResPrf struct { + Tenant string + ID string } // GetResourceProfile returns a resource configuration -func (apierV1 *ApierV1) GetResourceProfile(attr AttrGetResPrf, reply *engine.ResourceProfile) error { - if missing := utils.MissingStructFields(&attr, []string{"ID"}); len(missing) != 0 { //Params missing +func (apierV1 *ApierV1) GetResourceProfile(arg ArgGetResPrf, reply *engine.ResourceProfile) error { + if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing return utils.NewErrMandatoryIeMissing(missing...) } - if rcfg, err := apierV1.DataDB.GetResourceProfile(attr.ID, true, utils.NonTransactional); err != nil { + if rcfg, err := apierV1.DataDB.GetResourceProfile(arg.Tenant, arg.ID, true, utils.NonTransactional); err != nil { if err.Error() != utils.ErrNotFound.Error() { err = utils.NewErrServerError(err) } @@ -102,11 +103,11 @@ func (apierV1 *ApierV1) GetResourceProfile(attr AttrGetResPrf, reply *engine.Res } //SetResourceProfile add a new resource configuration -func (apierV1 *ApierV1) SetResourceProfile(attr *engine.ResourceProfile, reply *string) error { - if missing := utils.MissingStructFields(attr, []string{"ID"}); len(missing) != 0 { +func (apierV1 *ApierV1) SetResourceProfile(res *engine.ResourceProfile, reply *string) error { + if missing := utils.MissingStructFields(res, []string{"Tenant", "ID"}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } - if err := apierV1.DataDB.SetResourceProfile(attr, utils.NonTransactional); err != nil { + if err := apierV1.DataDB.SetResourceProfile(res, utils.NonTransactional); err != nil { return utils.APIErrorHandler(err) } *reply = utils.OK @@ -114,11 +115,11 @@ func (apierV1 *ApierV1) SetResourceProfile(attr *engine.ResourceProfile, reply * } //RemResourceProfile remove a specific resource configuration -func (apierV1 *ApierV1) RemResourceProfile(attrs AttrGetResPrf, reply *string) error { - if missing := utils.MissingStructFields(&attrs, []string{"ID"}); len(missing) != 0 { //Params missing +func (apierV1 *ApierV1) RemResourceProfile(arg ArgGetResPrf, reply *string) error { + if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing return utils.NewErrMandatoryIeMissing(missing...) } - if err := apierV1.DataDB.RemoveResourceProfile(attrs.ID, utils.NonTransactional); err != nil { + if err := apierV1.DataDB.RemoveResourceProfile(arg.Tenant, arg.ID, utils.NonTransactional); err != nil { if err.Error() != utils.ErrNotFound.Error() { err = utils.NewErrServerError(err) } diff --git a/engine/resources.go b/engine/resources.go index 5936ba07e..422385269 100755 --- a/engine/resources.go +++ b/engine/resources.go @@ -82,6 +82,11 @@ type Resource struct { rPrf *ResourceProfile // for ordering purposes } +// TenantID returns the unique ID in a multi-tenant environment +func (r *Resource) TenantID() string { + return utils.ConcatenatedKey(r.Tenant, r.ID) +} + // removeExpiredUnits removes units which are expired from the resource func (r *Resource) removeExpiredUnits() { var firstActive int @@ -187,13 +192,21 @@ func (rs Resources) clearUsage(ruID string) (err error) { return } -// ids returns list of resource IDs in resources -func (rs Resources) ids() (ids []string) { - ids = make([]string, len(rs)) +// tenantIDs returns list of TenantIDs in resources +func (rs Resources) tenantIDs() []*utils.TenantID { + tntIDs := make([]*utils.TenantID, len(rs)) for i, r := range rs { - ids[i] = r.ID + tntIDs[i] = &utils.TenantID{r.Tenant, r.ID} } - return + return tntIDs +} + +func (rs Resources) tenatIDsStr() []string { + ids := make([]string, len(rs)) + for i, r := range rs { + ids[i] = r.TenantID() + } + return ids } // AllocateResource attempts allocating resources for a *ResourceUsage @@ -203,7 +216,7 @@ func (rs Resources) AllocateResource(ru *ResourceUsage, dryRun bool) (alcMessage if len(rs) == 0 { return "", utils.ErrResourceUnavailable } - lockIDs := utils.PrefixSliceItems(rs.ids(), utils.ResourcesPrefix) + lockIDs := utils.PrefixSliceItems(rs.tenatIDsStr(), utils.ResourcesPrefix) guardian.Guardian.GuardIDs(config.CgrConfig().LockingTimeout, lockIDs...) defer guardian.Guardian.UnguardIDs(lockIDs...) // Simulate resource usage @@ -234,7 +247,7 @@ func NewResourceService(dataDB DataDB, storeInterval time.Duration, statS = nil } return &ResourceService{dataDB: dataDB, statS: statS, - lcEventResources: make(map[string][]string), + lcEventResources: make(map[string][]*utils.TenantID), storedResources: make(utils.StringMap), storeInterval: storeInterval, stopBackup: make(chan struct{})}, nil } @@ -243,7 +256,7 @@ func NewResourceService(dataDB DataDB, storeInterval time.Duration, type ResourceService struct { dataDB DataDB // So we can load the data in cache and index it statS rpcclient.RpcClientConnection // allows applying filters based on stats - lcEventResources map[string][]string // cache recording resources for events in alocation phase + lcEventResources map[string][]*utils.TenantID // cache recording resources for events in alocation phase lcERMux sync.RWMutex // protects the lcEventResources storedResources utils.StringMap // keep a record of resources which need saving, map[resID]bool srMux sync.RWMutex // protects storedResources @@ -340,7 +353,7 @@ func (rS *ResourceService) cachedResourcesForEvent(evUUID string) (rs Resources) if rIDsIf, has := cache.Get(utils.EventResourcesPrefix + evUUID); !has { return nil } else if rIDsIf != nil { - rIDs = rIDsIf.([]string) + rIDs = rIDsIf.([]*utils.TenantID) } shortCached = true } @@ -348,11 +361,14 @@ func (rS *ResourceService) cachedResourcesForEvent(evUUID string) (rs Resources) if len(rIDs) == 0 { return } - lockIDs := utils.PrefixSliceItems(rIDs, utils.ResourcesPrefix) + lockIDs := make([]string, len(rIDs)) + for i, rTid := range rIDs { + lockIDs[i] = utils.ResourcesPrefix + rTid.TenantID() + } guardian.Guardian.GuardIDs(config.CgrConfig().LockingTimeout, lockIDs...) defer guardian.Guardian.UnguardIDs(lockIDs...) - for i, rID := range rIDs { - if r, err := rS.dataDB.GetResource(rID, false, ""); err != nil { + for i, rTid := range rIDs { + if r, err := rS.dataDB.GetResource(rTid.Tenant, rTid.ID, false, ""); err != nil { utils.Logger.Warning( fmt.Sprintf(" force-uncaching resources for evUUID: <%s>, error: <%s>", evUUID, err.Error())) @@ -383,7 +399,8 @@ func (rS *ResourceService) matchingResourcesForEvent(ev map[string]interface{}) guardian.Guardian.GuardIDs(config.CgrConfig().LockingTimeout, lockIDs...) defer guardian.Guardian.UnguardIDs(lockIDs...) for resName := range rIDs { - rPrf, err := rS.dataDB.GetResourceProfile(resName, false, utils.NonTransactional) + rTntID := utils.NewTenantID(resName) + rPrf, err := rS.dataDB.GetResourceProfile(rTntID.Tenant, rTntID.ID, false, utils.NonTransactional) if err != nil { if err == utils.ErrNotFound { continue @@ -406,7 +423,7 @@ func (rS *ResourceService) matchingResourcesForEvent(ev map[string]interface{}) if !passAllFilters { continue } - r, err := rS.dataDB.GetResource(rPrf.ID, false, "") + r, err := rS.dataDB.GetResource(rPrf.Tenant, rPrf.ID, false, "") if err != nil { return nil, err } @@ -455,7 +472,7 @@ func (rS *ResourceService) V1AllowUsage(args utils.AttrRLsResourceUsage, allow * if mtcRLs, err = rS.matchingResourcesForEvent(args.Event); err != nil { return err } - cache.Set(utils.EventResourcesPrefix+args.UsageID, mtcRLs.ids(), true, "") + cache.Set(utils.EventResourcesPrefix+args.UsageID, mtcRLs.tenantIDs(), true, "") } if _, err = mtcRLs.AllocateResource( &ResourceUsage{ID: args.UsageID, @@ -498,7 +515,7 @@ func (rS *ResourceService) V1AllocateResource(args utils.AttrRLsResourceUsage, r } if wasShortCached || !wasCached { rS.lcERMux.Lock() - rS.lcEventResources[args.UsageID] = mtcRLs.ids() + rS.lcEventResources[args.UsageID] = mtcRLs.tenantIDs() rS.lcERMux.Unlock() } // index it for storing diff --git a/engine/storage_interface.go b/engine/storage_interface.go index 9b4c4cb92..dc199ccc8 100755 --- a/engine/storage_interface.go +++ b/engine/storage_interface.go @@ -99,12 +99,12 @@ type DataDB interface { RemoveAlias(string, string) error SetReverseAlias(*Alias, string) error GetReverseAlias(string, bool, string) ([]string, error) - GetResourceProfile(string, bool, string) (*ResourceProfile, error) + GetResourceProfile(string, string, bool, string) (*ResourceProfile, error) SetResourceProfile(*ResourceProfile, string) error - RemoveResourceProfile(string, string) error - GetResource(string, bool, string) (*Resource, error) + RemoveResourceProfile(string, string, string) error + GetResource(string, string, bool, string) (*Resource, error) SetResource(*Resource) error - RemoveResource(string, string) error + RemoveResource(string, string, string) error GetTiming(string, bool, string) (*utils.TPTiming, error) SetTiming(*utils.TPTiming, string) error RemoveTiming(string, string) error diff --git a/engine/storage_map.go b/engine/storage_map.go index bc7d7780b..fd7359a56 100755 --- a/engine/storage_map.go +++ b/engine/storage_map.go @@ -193,6 +193,7 @@ func (ms *MapStorage) PreloadCacheForPrefix(prefix string) error { // CacheDataFromDB loads data to cache, // prefix represents the cache prefix, IDs should be nil if all available data should be loaded +// ToDo: convert IDs into []*utils.TenantIDs when infrastructure will be ready func (ms *MapStorage) CacheDataFromDB(prefix string, IDs []string, mustBeCached bool) (err error) { if !utils.IsSliceMember([]string{utils.DESTINATION_PREFIX, utils.REVERSE_DESTINATION_PREFIX, @@ -273,9 +274,11 @@ func (ms *MapStorage) CacheDataFromDB(prefix string, IDs []string, mustBeCached case utils.REVERSE_ALIASES_PREFIX: _, err = ms.GetReverseAlias(dataID, true, utils.NonTransactional) case utils.ResourceProfilesPrefix: - _, err = ms.GetResourceProfile(dataID, true, utils.NonTransactional) + tntID := utils.NewTenantID(dataID) + _, err = ms.GetResourceProfile(tntID.Tenant, tntID.ID, true, utils.NonTransactional) case utils.ResourcesPrefix: - _, err = ms.GetResource(dataID, true, utils.NonTransactional) + tntID := utils.NewTenantID(dataID) + _, err = ms.GetResource(tntID.Tenant, tntID.ID, true, utils.NonTransactional) case utils.TimingsPrefix: _, err = ms.GetTiming(dataID, true, utils.NonTransactional) } @@ -1276,10 +1279,10 @@ func (ms *MapStorage) GetSMCost(cgrid, source, runid, originHost, originID strin return } -func (ms *MapStorage) GetResourceProfile(id string, skipCache bool, transactionID string) (rsp *ResourceProfile, err error) { +func (ms *MapStorage) GetResourceProfile(tenant, id string, skipCache bool, transactionID string) (rsp *ResourceProfile, err error) { ms.mu.RLock() defer ms.mu.RUnlock() - key := utils.ResourceProfilesPrefix + id + key := utils.ResourceProfilesPrefix + utils.ConcatenatedKey(tenant, id) if !skipCache { if x, ok := cache.Get(key); ok { if x != nil { @@ -1313,23 +1316,23 @@ func (ms *MapStorage) SetResourceProfile(r *ResourceProfile, transactionID strin if err != nil { return err } - ms.dict[utils.ResourceProfilesPrefix+r.ID] = result + ms.dict[utils.ResourceProfilesPrefix+r.TenantID()] = result return nil } -func (ms *MapStorage) RemoveResourceProfile(id string, transactionID string) error { +func (ms *MapStorage) RemoveResourceProfile(tenant, id string, transactionID string) error { ms.mu.Lock() defer ms.mu.Unlock() - key := utils.ResourceProfilesPrefix + id + key := utils.ResourceProfilesPrefix + utils.ConcatenatedKey(tenant, id) delete(ms.dict, key) cache.RemKey(key, cacheCommit(transactionID), transactionID) return nil } -func (ms *MapStorage) GetResource(id string, skipCache bool, transactionID string) (r *Resource, err error) { +func (ms *MapStorage) GetResource(tenant, id string, skipCache bool, transactionID string) (r *Resource, err error) { ms.mu.RLock() defer ms.mu.RUnlock() - key := utils.ResourcesPrefix + id + key := utils.ResourcesPrefix + utils.ConcatenatedKey(tenant, id) if !skipCache { if x, ok := cache.Get(key); ok { if x != nil { @@ -1358,14 +1361,14 @@ func (ms *MapStorage) SetResource(r *Resource) (err error) { if err != nil { return err } - ms.dict[utils.ResourcesPrefix+r.ID] = result + ms.dict[utils.ResourcesPrefix+r.TenantID()] = result return } -func (ms *MapStorage) RemoveResource(id string, transactionID string) (err error) { +func (ms *MapStorage) RemoveResource(tenant, id string, transactionID string) (err error) { ms.mu.Lock() defer ms.mu.Unlock() - key := utils.ResourcesPrefix + id + key := utils.ResourcesPrefix + utils.ConcatenatedKey(tenant, id) delete(ms.dict, key) cache.RemKey(key, cacheCommit(transactionID), transactionID) return diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go index 66f6fb984..11cd4448b 100755 --- a/engine/storage_mongo_datadb.go +++ b/engine/storage_mongo_datadb.go @@ -526,9 +526,11 @@ func (ms *MongoStorage) CacheDataFromDB(prfx string, ids []string, mustBeCached case utils.REVERSE_ALIASES_PREFIX: _, err = ms.GetReverseAlias(dataID, true, utils.NonTransactional) case utils.ResourceProfilesPrefix: - _, err = ms.GetResourceProfile(dataID, true, utils.NonTransactional) + tntID := utils.NewTenantID(dataID) + _, err = ms.GetResourceProfile(tntID.Tenant, tntID.ID, true, utils.NonTransactional) case utils.ResourcesPrefix: - _, err = ms.GetResource(dataID, true, utils.NonTransactional) + tntID := utils.NewTenantID(dataID) + _, err = ms.GetResource(tntID.Tenant, tntID.ID, true, utils.NonTransactional) case utils.TimingsPrefix: _, err = ms.GetTiming(dataID, true, utils.NonTransactional) } @@ -1830,8 +1832,8 @@ func (ms *MongoStorage) GetAllCdrStats() (css []*CdrStats, err error) { return } -func (ms *MongoStorage) GetResourceProfile(id string, skipCache bool, transactionID string) (rp *ResourceProfile, err error) { - key := utils.ResourceProfilesPrefix + id +func (ms *MongoStorage) GetResourceProfile(tenant, id string, skipCache bool, transactionID string) (rp *ResourceProfile, err error) { + key := utils.ResourceProfilesPrefix + utils.ConcatenatedKey(tenant, id) if !skipCache { if x, ok := cache.Get(key); ok { if x == nil { @@ -1843,7 +1845,7 @@ func (ms *MongoStorage) GetResourceProfile(id string, skipCache bool, transactio session, col := ms.conn(colRsP) defer session.Close() rp = new(ResourceProfile) - if err = col.Find(bson.M{"id": id}).One(rp); err != nil { + if err = col.Find(bson.M{"tenant": tenant, "id": id}).One(rp); err != nil { if err == mgo.ErrNotFound { err = utils.ErrNotFound cache.Set(key, nil, cacheCommit(transactionID), transactionID) @@ -1862,22 +1864,23 @@ func (ms *MongoStorage) GetResourceProfile(id string, skipCache bool, transactio func (ms *MongoStorage) SetResourceProfile(rp *ResourceProfile, transactionID string) (err error) { session, col := ms.conn(colRsP) defer session.Close() - _, err = col.Upsert(bson.M{"id": rp.ID}, rp) + _, err = col.Upsert(bson.M{"tenant": rp.Tenant, "id": rp.ID}, rp) return } -func (ms *MongoStorage) RemoveResourceProfile(id string, transactionID string) (err error) { +func (ms *MongoStorage) RemoveResourceProfile(tenant, id string, transactionID string) (err error) { session, col := ms.conn(colRsP) defer session.Close() - if err = col.Remove(bson.M{"id": id}); err != nil { + if err = col.Remove(bson.M{"tenant": tenant, "id": id}); err != nil { return } - cache.RemKey(utils.ResourceProfilesPrefix+id, cacheCommit(transactionID), transactionID) + cache.RemKey(utils.ResourceProfilesPrefix+utils.ConcatenatedKey(tenant, id), + cacheCommit(transactionID), transactionID) return nil } -func (ms *MongoStorage) GetResource(id string, skipCache bool, transactionID string) (r *Resource, err error) { - key := utils.ResourcesPrefix + id +func (ms *MongoStorage) GetResource(tenant, id string, skipCache bool, transactionID string) (r *Resource, err error) { + key := utils.ResourcesPrefix + utils.ConcatenatedKey(tenant, id) if !skipCache { if x, ok := cache.Get(key); ok { if x == nil { @@ -1889,7 +1892,7 @@ func (ms *MongoStorage) GetResource(id string, skipCache bool, transactionID str session, col := ms.conn(colRes) defer session.Close() r = new(Resource) - if err = col.Find(bson.M{"id": id}).One(r); err != nil { + if err = col.Find(bson.M{"tenant": tenant, "id": id}).One(r); err != nil { if err == mgo.ErrNotFound { err = utils.ErrNotFound cache.Set(key, nil, cacheCommit(transactionID), transactionID) @@ -1903,17 +1906,18 @@ func (ms *MongoStorage) GetResource(id string, skipCache bool, transactionID str func (ms *MongoStorage) SetResource(r *Resource) (err error) { session, col := ms.conn(colRes) defer session.Close() - _, err = col.Upsert(bson.M{"id": r.ID}, r) + _, err = col.Upsert(bson.M{"tenant": r.Tenant, "id": r.ID}, r) return } -func (ms *MongoStorage) RemoveResource(id string, transactionID string) (err error) { +func (ms *MongoStorage) RemoveResource(tenant, id string, transactionID string) (err error) { session, col := ms.conn(colRes) defer session.Close() - if err = col.Remove(bson.M{"id": id}); err != nil { + if err = col.Remove(bson.M{"tenant": tenant, "id": id}); err != nil { return } - cache.RemKey(utils.ResourcesPrefix+id, cacheCommit(transactionID), transactionID) + cache.RemKey(utils.ResourcesPrefix+utils.ConcatenatedKey(tenant, id), + cacheCommit(transactionID), transactionID) return nil } diff --git a/engine/storage_redis.go b/engine/storage_redis.go index db1ae044d..0b50bb8b2 100755 --- a/engine/storage_redis.go +++ b/engine/storage_redis.go @@ -288,9 +288,11 @@ func (rs *RedisStorage) CacheDataFromDB(prfx string, ids []string, mustBeCached case utils.REVERSE_ALIASES_PREFIX: _, err = rs.GetReverseAlias(dataID, true, utils.NonTransactional) case utils.ResourceProfilesPrefix: - _, err = rs.GetResourceProfile(dataID, true, utils.NonTransactional) + tntID := utils.NewTenantID(dataID) + _, err = rs.GetResourceProfile(tntID.Tenant, tntID.ID, true, utils.NonTransactional) case utils.ResourcesPrefix: - _, err = rs.GetResource(dataID, true, utils.NonTransactional) + tntID := utils.NewTenantID(dataID) + _, err = rs.GetResource(tntID.Tenant, tntID.ID, true, utils.NonTransactional) case utils.TimingsPrefix: _, err = rs.GetTiming(dataID, true, utils.NonTransactional) } @@ -1350,8 +1352,8 @@ func (rs *RedisStorage) GetAllCdrStats() (css []*CdrStats, err error) { return } -func (rs *RedisStorage) GetResourceProfile(id string, skipCache bool, transactionID string) (rsp *ResourceProfile, err error) { - key := utils.ResourceProfilesPrefix + id +func (rs *RedisStorage) GetResourceProfile(tenant, id string, skipCache bool, transactionID string) (rsp *ResourceProfile, err error) { + key := utils.ResourceProfilesPrefix + utils.ConcatenatedKey(tenant, id) if !skipCache { if x, ok := cache.Get(key); ok { if x == nil { @@ -1385,11 +1387,11 @@ func (rs *RedisStorage) SetResourceProfile(rsp *ResourceProfile, transactionID s if err != nil { return err } - return rs.Cmd("SET", utils.ResourceProfilesPrefix+rsp.ID, result).Err + return rs.Cmd("SET", utils.ResourceProfilesPrefix+rsp.TenantID(), result).Err } -func (rs *RedisStorage) RemoveResourceProfile(id string, transactionID string) (err error) { - key := utils.ResourceProfilesPrefix + id +func (rs *RedisStorage) RemoveResourceProfile(tenant, id string, transactionID string) (err error) { + key := utils.ResourceProfilesPrefix + utils.ConcatenatedKey(tenant, id) if err = rs.Cmd("DEL", key).Err; err != nil { return } @@ -1397,8 +1399,8 @@ func (rs *RedisStorage) RemoveResourceProfile(id string, transactionID string) ( return } -func (rs *RedisStorage) GetResource(id string, skipCache bool, transactionID string) (r *Resource, err error) { - key := utils.ResourcesPrefix + id +func (rs *RedisStorage) GetResource(tenant, id string, skipCache bool, transactionID string) (r *Resource, err error) { + key := utils.ResourcesPrefix + utils.ConcatenatedKey(tenant, id) if !skipCache { if x, ok := cache.Get(key); ok { if x == nil { @@ -1427,11 +1429,11 @@ func (rs *RedisStorage) SetResource(r *Resource) (err error) { if err != nil { return err } - return rs.Cmd("SET", utils.ResourcesPrefix+r.ID, result).Err + return rs.Cmd("SET", utils.ResourcesPrefix+r.TenantID(), result).Err } -func (rs *RedisStorage) RemoveResource(id string, transactionID string) (err error) { - key := utils.ResourcesPrefix + id +func (rs *RedisStorage) RemoveResource(tenant, id string, transactionID string) (err error) { + key := utils.ResourcesPrefix + utils.ConcatenatedKey(tenant, id) if err = rs.Cmd("DEL", key).Err; err != nil { return } From bdafd9913742bf88a65dda0043e4b963fa060fa9 Mon Sep 17 00:00:00 2001 From: DanB Date: Fri, 15 Sep 2017 14:54:10 +0200 Subject: [PATCH 3/3] Storage mongo returning TenantID from getKeysForPrefix for resource and resource profiles --- engine/loader_it_test.go | 24 ++++++++++--------- engine/onstor_it_test.go | 43 ++++++++++++++++++---------------- engine/storage_mongo_datadb.go | 10 ++++---- 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/engine/loader_it_test.go b/engine/loader_it_test.go index 476480f2c..8528ac7a7 100755 --- a/engine/loader_it_test.go +++ b/engine/loader_it_test.go @@ -309,17 +309,19 @@ func TestLoaderITWriteToDatabase(t *testing.T) { } } - for k, rl := range loader.resProfiles { - rcv, err := loader.dataStorage.GetResourceProfile(k, true, utils.NonTransactional) - if err != nil { - t.Error("Failed GetResourceProfile: ", err.Error()) - } - rlT, err := APItoResource(rl, "UTC") - if err != nil { - t.Error(err) - } - if !reflect.DeepEqual(rlT, rcv) { - t.Errorf("Expecting: %v, received: %v", rlT, rcv) + for _, mapIDs := range loader.resProfiles { + for _, rl := range mapIDs { + rcv, err := loader.dataStorage.GetResourceProfile(rl.Tenant, rl.ID, true, utils.NonTransactional) + if err != nil { + t.Error("Failed GetResourceProfile: ", err.Error()) + } + rlT, err := APItoResource(rl, "UTC") + if err != nil { + t.Error(err) + } + if !reflect.DeepEqual(rlT, rcv) { + t.Errorf("Expecting: %v, received: %v", rlT, rcv) + } } } diff --git a/engine/onstor_it_test.go b/engine/onstor_it_test.go index f5b4709a1..b267baa22 100644 --- a/engine/onstor_it_test.go +++ b/engine/onstor_it_test.go @@ -782,6 +782,7 @@ func testOnStorITCacheReverseAlias(t *testing.T) { func testOnStorITCacheResourceProfile(t *testing.T) { rCfg := &ResourceProfile{ + Tenant: "cgrates.org", ID: "RL_TEST", Weight: 10, Filters: []*RequestFilter{ @@ -799,19 +800,19 @@ func testOnStorITCacheResourceProfile(t *testing.T) { if err := onStor.SetResourceProfile(rCfg, utils.NonTransactional); err != nil { t.Error(err) } - expectedR := []string{"rsp_RL_TEST"} + expectedR := []string{"rsp_cgrates.org:RL_TEST"} if itm, err := onStor.GetKeysForPrefix(utils.ResourceProfilesPrefix); err != nil { t.Error(err) } else if !reflect.DeepEqual(expectedR, itm) { t.Errorf("Expected : %+v, but received %+v", expectedR, itm) } - if _, hasIt := cache.Get(utils.ResourceProfilesPrefix + rCfg.ID); hasIt { + if _, hasIt := cache.Get(utils.ResourceProfilesPrefix + rCfg.TenantID()); hasIt { t.Error("Already in cache") } - if err := onStor.CacheDataFromDB(utils.ResourceProfilesPrefix, []string{rCfg.ID}, false); err != nil { + if err := onStor.CacheDataFromDB(utils.ResourceProfilesPrefix, []string{rCfg.TenantID()}, false); err != nil { t.Error(err) } - if itm, hasIt := cache.Get(utils.ResourceProfilesPrefix + rCfg.ID); !hasIt { + if itm, hasIt := cache.Get(utils.ResourceProfilesPrefix + rCfg.TenantID()); !hasIt { t.Error("Did not cache") } else if rcv := itm.(*ResourceProfile); !reflect.DeepEqual(rCfg, rcv) { t.Errorf("Expecting: %+v, received: %+v", rCfg, rcv) @@ -853,7 +854,8 @@ func testOnStorITCacheTiming(t *testing.T) { func testOnStorITCacheResource(t *testing.T) { res := &Resource{ - ID: "RL1", + Tenant: "cgrates.org", + ID: "RL1", Usages: map[string]*ResourceUsage{ "RU1": &ResourceUsage{ ID: "RU1", @@ -866,20 +868,20 @@ func testOnStorITCacheResource(t *testing.T) { if err := onStor.SetResource(res); err != nil { t.Error(err) } - expectedT := []string{"res_RL1"} + expectedT := []string{"res_cgrates.org:RL1"} if itm, err := onStor.GetKeysForPrefix(utils.ResourcesPrefix); err != nil { t.Error(err) } else if !reflect.DeepEqual(expectedT, itm) { t.Errorf("Expected : %+v, but received %+v", expectedT, itm) } - if _, hasIt := cache.Get(utils.ResourcesPrefix + res.ID); hasIt { + if _, hasIt := cache.Get(utils.ResourcesPrefix + res.TenantID()); hasIt { t.Error("Already in cache") } - if err := onStor.CacheDataFromDB(utils.ResourcesPrefix, []string{res.ID}, false); err != nil { + if err := onStor.CacheDataFromDB(utils.ResourcesPrefix, []string{res.TenantID()}, false); err != nil { t.Error(err) } - if itm, hasIt := cache.Get(utils.ResourcesPrefix + res.ID); !hasIt { + if itm, hasIt := cache.Get(utils.ResourcesPrefix + res.TenantID()); !hasIt { t.Error("Did not cache") } else if rcv := itm.(*Resource); !reflect.DeepEqual(res, rcv) { t.Errorf("Expecting: %+v, received: %+v", res, rcv) @@ -1798,13 +1800,13 @@ func testOnStorITCRUDResourceProfile(t *testing.T) { Thresholds: []string{"TEST_ACTIONS"}, UsageTTL: time.Duration(1 * time.Millisecond), } - if _, rcvErr := onStor.GetResourceProfile(rL.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound { + if _, rcvErr := onStor.GetResourceProfile(rL.Tenant, rL.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound { t.Error(rcvErr) } if err := onStor.SetResourceProfile(rL, utils.NonTransactional); err != nil { t.Error(err) } - if rcv, err := onStor.GetResourceProfile(rL.ID, true, utils.NonTransactional); err != nil { + if rcv, err := onStor.GetResourceProfile(rL.Tenant, rL.ID, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(rL, rcv) { t.Errorf("Expecting: %v, received: %v", rL, rcv) @@ -1817,7 +1819,7 @@ func testOnStorITCRUDResourceProfile(t *testing.T) { // t.Error(rcvErr) // } // - if rcv, err := onStor.GetResourceProfile(rL.ID, false, utils.NonTransactional); err != nil { + if rcv, err := onStor.GetResourceProfile(rL.Tenant, rL.ID, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(rL, rcv) { t.Errorf("Expecting: %v, received: %v", rL, rcv) @@ -1825,17 +1827,18 @@ func testOnStorITCRUDResourceProfile(t *testing.T) { // if err = onStor.SelectDatabase(onStorCfg); err != nil { // t.Error(err) // } - if err := onStor.RemoveResourceProfile(rL.ID, utils.NonTransactional); err != nil { + if err := onStor.RemoveResourceProfile(rL.Tenant, rL.ID, utils.NonTransactional); err != nil { t.Error(err) } - if _, rcvErr := onStor.GetResourceProfile(rL.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound { + if _, rcvErr := onStor.GetResourceProfile(rL.Tenant, rL.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound { t.Error(rcvErr) } } func testOnStorITCRUDResource(t *testing.T) { res := &Resource{ - ID: "RL1", + Tenant: "cgrates.org", + ID: "RL1", Usages: map[string]*ResourceUsage{ "RU1": &ResourceUsage{ ID: "RU1", @@ -1845,26 +1848,26 @@ func testOnStorITCRUDResource(t *testing.T) { }, TTLIdx: []string{"RU1"}, } - if _, rcvErr := onStor.GetResource("RL1", true, utils.NonTransactional); rcvErr != nil && rcvErr != utils.ErrNotFound { + if _, rcvErr := onStor.GetResource("cgrates.org", "RL1", true, utils.NonTransactional); rcvErr != nil && rcvErr != utils.ErrNotFound { t.Error(rcvErr) } if err := onStor.SetResource(res); err != nil { t.Error(err) } - if rcv, err := onStor.GetResource("RL1", true, utils.NonTransactional); err != nil { + if rcv, err := onStor.GetResource("cgrates.org", "RL1", true, utils.NonTransactional); err != nil { t.Error(err) } else if !(reflect.DeepEqual(res, rcv)) { t.Errorf("Expecting: %v, received: %v", res, rcv) } - if rcv, err := onStor.GetResource("RL1", false, utils.NonTransactional); err != nil { + if rcv, err := onStor.GetResource("cgrates.org", "RL1", false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(res, rcv) { t.Errorf("Expecting: %v, received: %v", res, rcv) } - if err := onStor.RemoveResource(res.ID, utils.NonTransactional); err != nil { + if err := onStor.RemoveResource(res.Tenant, res.ID, utils.NonTransactional); err != nil { t.Error(err) } - if _, rcvErr := onStor.GetResource(res.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound { + if _, rcvErr := onStor.GetResource(res.Tenant, res.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound { t.Error(rcvErr) } } diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go index 11cd4448b..95476f443 100755 --- a/engine/storage_mongo_datadb.go +++ b/engine/storage_mongo_datadb.go @@ -556,7 +556,7 @@ func (ms *MongoStorage) GetKeysForPrefix(prefix string) (result []string, err er defer session.Close() db := session.DB(ms.db) keyResult := struct{ Key string }{} - idResult := struct{ Id string }{} + idResult := struct{ Tenant, Id string }{} switch category { case utils.DESTINATION_PREFIX: iter := db.C(colDst).Find(bson.M{"key": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"key": 1}).Iter() @@ -624,14 +624,14 @@ func (ms *MongoStorage) GetKeysForPrefix(prefix string) (result []string, err er result = append(result, utils.REVERSE_ALIASES_PREFIX+keyResult.Key) } case utils.ResourceProfilesPrefix: - iter := db.C(colRsP).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"id": 1}).Iter() + iter := db.C(colRsP).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"tenant": 1, "id": 1}).Iter() for iter.Next(&idResult) { - result = append(result, utils.ResourceProfilesPrefix+idResult.Id) + result = append(result, utils.ResourceProfilesPrefix+utils.ConcatenatedKey(idResult.Tenant, idResult.Id)) } case utils.ResourcesPrefix: - iter := db.C(colRes).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"id": 1}).Iter() + iter := db.C(colRes).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"tenant": 1, "id": 1}).Iter() for iter.Next(&idResult) { - result = append(result, utils.ResourcesPrefix+idResult.Id) + result = append(result, utils.ResourcesPrefix+utils.ConcatenatedKey(idResult.Tenant, idResult.Id)) } case utils.StatQueuePrefix: iter := db.C(colStq).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"id": 1}).Iter()