From 0ef0f0f391bd57b6b86c40de9f0819111cd54327 Mon Sep 17 00:00:00 2001 From: ns019t Date: Thu, 8 Aug 2019 15:00:21 +0300 Subject: [PATCH] [RICPLT-1740] - Get Ran Load Information API Change-Id: Ib14fa36f3c5bcd8ab0c4e47363263cd4819294ab Signed-off-by: ns019t --- common/rNibPool_test.go | 2 +- reader/rNibReader.go | 31 ++++++ reader/rNibReader_test.go | 242 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 256 insertions(+), 19 deletions(-) diff --git a/common/rNibPool_test.go b/common/rNibPool_test.go index c8f0c00..e3bffa5 100644 --- a/common/rNibPool_test.go +++ b/common/rNibPool_test.go @@ -68,8 +68,8 @@ func validateMaxLimit(size int, iterations int, t *testing.T) { ) group := sync.WaitGroup{} for i := 0; i < iterations; i++ { + group.Add(1) go func() { - group.Add(1) getPutInstance() group.Done() }() diff --git a/reader/rNibReader.go b/reader/rNibReader.go index ae9dcf3..0509326 100644 --- a/reader/rNibReader.go +++ b/reader/rNibReader.go @@ -22,6 +22,7 @@ import ( "gerrit.o-ran-sc.org/r/ric-plt/sdlgo" "github.com/golang/protobuf/proto" "github.com/pkg/errors" + "reflect" ) var readerPool *common.Pool @@ -53,6 +54,8 @@ type RNibReader interface { GetCellById(cellType entities.Cell_Type, cellId string) (*entities.Cell, common.IRNibError) // GetListNodebIds returns the full list of Nodeb identity entities GetListNodebIds()([]*entities.NbIdentity, common.IRNibError) + // GetRanLoadInformation retrieves nodeb load information entity from redis DB by nodeb inventory name + GetRanLoadInformation(inventoryName string) (*entities.RanLoadInformation, common.IRNibError) } const( @@ -180,6 +183,34 @@ func (w *rNibReaderInstance) GetListNodebIds()([]*entities.NbIdentity, common.IR return *data, rnibErr } +func (w *rNibReaderInstance) GetRanLoadInformation(inventoryName string) (*entities.RanLoadInformation, common.IRNibError){ + key, rNibErr := common.ValidateAndBuildRanLoadInformationKey(inventoryName) + if rNibErr != nil { + return nil, rNibErr + } + loadInfo := &entities.RanLoadInformation{} + err := w.getByKeyAndUnmarshal(key, loadInfo) + if err!= nil{ + return nil, err + } + return loadInfo, err +} + +func (w *rNibReaderInstance) getByKeyAndUnmarshal(key string, entity proto.Message)common.IRNibError{ + data, err := (*w.sdl).Get([]string{key}) + if err != nil { + return common.NewInternalError(err) + } + if data != nil && data[key] != nil { + err = proto.Unmarshal([]byte(data[key].(string)), entity) + if err != nil { + return common.NewInternalError(err) + } + return nil + } + return common.NewResourceNotFoundError(errors.Errorf("#rNibReader.getByKeyAndUnmarshal - entity of type %s not found. Key: %s", reflect.TypeOf(entity).String(), key)) +} + func (w *rNibReaderInstance) getNodeb(key string) (*entities.NodebInfo, common.IRNibError) { data, err := (*w.sdl).Get([]string{key}) if err != nil { diff --git a/reader/rNibReader_test.go b/reader/rNibReader_test.go index 35e9cb9..ad19ab4 100644 --- a/reader/rNibReader_test.go +++ b/reader/rNibReader_test.go @@ -17,12 +17,14 @@ package reader import ( + "encoding/json" "errors" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" "github.com/golang/protobuf/proto" "github.com/stretchr/testify/assert" "testing" + "time" ) var namespace = "namespace" @@ -86,8 +88,12 @@ func TestGetNodeB(t *testing.T) { if err != nil { t.Errorf("#rNibReader_test.TestGetNb - Failed to marshal ENB instance. Error: %v", err) } - ret := map[string]interface{}{"RAN:" + name: string(data)} - sdlInstanceMock.On("Get", []string{"RAN:" + name}).Return(ret, e) + redisKey, rNibErr := common.ValidateAndBuildNodeBNameKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetNodeB - failed to validate key parameter") + } + ret := map[string]interface{}{redisKey: string(data)} + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) getNb, er := w.GetNodeb(name) assert.Nil(t, er) assert.Equal(t, getNb.Ip, nb.Ip) @@ -104,7 +110,11 @@ func TestGetNodeBNotFoundFailure(t *testing.T) { w := GetRNibReader() var e error var ret map[string]interface{} - sdlInstanceMock.On("Get", []string{"RAN:" + name}).Return(ret, e) + redisKey, rNibErr := common.ValidateAndBuildNodeBNameKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetNodeBNotFoundFailure - failed to validate key parameter") + } + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) getNb, er := w.GetNodeb(name) assert.NotNil(t, er) assert.Nil(t, getNb) @@ -119,8 +129,12 @@ func TestGetNodeBUnmarshalFailure(t *testing.T) { w := GetRNibReader() var e error ret := make(map[string]interface{}, 1) - ret["RAN:"+name] = "data" - sdlInstanceMock.On("Get", []string{"RAN:" + name}).Return(ret, e) + redisKey, rNibErr := common.ValidateAndBuildNodeBNameKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetNodeBUnmarshalFailure - failed to validate key parameter") + } + ret[redisKey] = "data" + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) getNb, er := w.GetNodeb(name) assert.NotNil(t, er) assert.Nil(t, getNb) @@ -137,7 +151,11 @@ func TestGetNodeBSdlgoFailure(t *testing.T) { w := GetRNibReader() e := errors.New(errMsg) var ret map[string]interface{} - sdlInstanceMock.On("Get", []string{"RAN:" + name}).Return(ret, e) + redisKey, rNibErr := common.ValidateAndBuildNodeBNameKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetNodeBSdlgoFailure - failed to validate key parameter") + } + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) getNb, er := w.GetNodeb(name) assert.NotNil(t, er) assert.Nil(t, getNb) @@ -163,8 +181,12 @@ func TestGetNodeBCellsListEnb(t *testing.T) { if err != nil { t.Errorf("#rNibReader_test.GetNodeBCellsList - Failed to marshal ENB instance. Error: %v", err) } - ret := map[string]interface{}{"RAN:" + name: string(data)} - sdlInstanceMock.On("Get", []string{"RAN:" + name}).Return(ret, e) + redisKey, rNibErr := common.ValidateAndBuildNodeBNameKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetNodeBCellsListEnb - failed to validate key parameter") + } + ret := map[string]interface{}{redisKey: string(data)} + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) cells, er := w.GetCellList(name) assert.Nil(t, er) assert.NotNil(t, cells) @@ -192,8 +214,12 @@ func TestGetNodeBCellsListGnb(t *testing.T) { if err != nil { t.Errorf("#rNibReader_test.GetNodeBCellsList - Failed to marshal GNB instance. Error: %v", err) } - ret := map[string]interface{}{"RAN:" + name: string(data)} - sdlInstanceMock.On("Get", []string{"RAN:" + name}).Return(ret, e) + redisKey, rNibErr := common.ValidateAndBuildNodeBNameKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetNodeBCellsListGnb - failed to validate key parameter") + } + ret := map[string]interface{}{redisKey: string(data)} + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) cells, er := w.GetCellList(name) assert.Nil(t, er) assert.NotNil(t, cells) @@ -209,8 +235,12 @@ func TestGetNodeBCellsListNodeUnmarshalFailure(t *testing.T) { w := GetRNibReader() var e error ret := make(map[string]interface{}, 1) - ret["RAN:"+name] = "data" - sdlInstanceMock.On("Get", []string{"RAN:" + name}).Return(ret, e) + redisKey, rNibErr := common.ValidateAndBuildNodeBNameKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetNodeBCellsListNodeUnmarshalFailure - failed to validate key parameter") + } + ret[redisKey] = "data" + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) cells, er := w.GetCellList(name) assert.NotNil(t, er) assert.Nil(t, cells) @@ -225,7 +255,11 @@ func TestGetNodeBCellsListNodeNotFoundFailure(t *testing.T) { w := GetRNibReader() var e error var ret map[string]interface{} - sdlInstanceMock.On("Get", []string{"RAN:" + name}).Return(ret, e) + redisKey, rNibErr := common.ValidateAndBuildNodeBNameKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetNodeBCellsListNodeNotFoundFailure - failed to validate key parameter") + } + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) cells, er := w.GetCellList(name) assert.NotNil(t, er) assert.Nil(t, cells) @@ -249,8 +283,12 @@ func TestGetNodeBCellsListNotFoundFailureEnb(t *testing.T) { if err != nil { t.Errorf("#rNibReader_test.TestGetNbCellsListNotFoundFailure - Failed to marshal ENB instance. Error: %v", err) } - ret := map[string]interface{}{"RAN:" + name: string(data)} - sdlInstanceMock.On("Get", []string{"RAN:" + name}).Return(ret, e) + redisKey, rNibErr := common.ValidateAndBuildNodeBNameKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetNodeBCellsListNotFoundFailureEnb - failed to validate key parameter") + } + ret := map[string]interface{}{redisKey: string(data)} + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) _, er := w.GetCellList(name) assert.NotNil(t, er) assert.EqualValues(t, "1 RESOURCE_NOT_FOUND - #rNibReader.GetCellList - served cells not found. Responding node RAN name: name.", er.Error()) @@ -270,10 +308,14 @@ func TestGetNodeBCellsListNotFoundFailureGnb(t *testing.T) { var e error data, err := proto.Marshal(&nb) if err != nil { - t.Errorf("#rNibReader_test.TestGetNbCellsListNotFoundFailure - Failed to marshal ENB instance. Error: %v", err) + t.Errorf("#rNibReader_test.TestGetNodeBCellsListNotFoundFailureGnb - Failed to marshal ENB instance. Error: %v", err) + } + redisKey, rNibErr := common.ValidateAndBuildNodeBNameKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetNodeBCellsListNotFoundFailureGnb - failed to validate key parameter") } - ret := map[string]interface{}{"RAN:" + name: string(data)} - sdlInstanceMock.On("Get", []string{"RAN:" + name}).Return(ret, e) + ret := map[string]interface{}{redisKey: string(data)} + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) _, er := w.GetCellList(name) assert.NotNil(t, er) assert.EqualValues(t, "1 RESOURCE_NOT_FOUND - #rNibReader.GetCellList - served cells not found. Responding node RAN name: name.", er.Error()) @@ -929,6 +971,170 @@ func TestGetCellByIdValidationFailureEnb(t *testing.T) { assert.EqualValues(t, "3 VALIDATION_ERROR - #utils.ValidateAndBuildCellIdKey - an empty cell id received", er.Error()) } +func TestGetRanLoadInformation(t *testing.T) { + name := "name" + readerPool = nil + sdlInstanceMock := initSdlInstanceMock(namespace, 1) + w := GetRNibReader() + loadInfo := generateRanLoadInformation() + var e error + data, err := proto.Marshal(loadInfo) + if err != nil { + t.Errorf("#rNibReader_test.TestGetRanLoadInformation - Failed to marshal RanLoadInformation entity. Error: %v", err) + } + redisKey, rNibErr := common.ValidateAndBuildRanLoadInformationKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetRanLoadInformationNotFoundFailure - failed to validate key parameter") + } + ret := map[string]interface{}{redisKey: string(data)} + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) + getLoadInfo, er := w.GetRanLoadInformation(name) + assert.Nil(t, er) + assert.NotNil(t, getLoadInfo) + expected, err := json.Marshal(loadInfo) + if err != nil { + t.Errorf("#rNibReader_test.TestGetRanLoadInformation - Failed to marshal RanLoadInformation entity. Error: %v", err) + } + actual, err := json.Marshal(getLoadInfo) + if err != nil { + t.Errorf("#rNibReader_test.TestGetRanLoadInformation - Failed to marshal RanLoadInformation entity. Error: %v", err) + } + assert.EqualValues(t, expected, actual) +} + +func TestGetRanLoadInformationNotFoundFailure(t *testing.T) { + name := "name" + readerPool = nil + sdlInstanceMock := initSdlInstanceMock(namespace, 1) + w := GetRNibReader() + var e error + var ret map[string]interface{} + redisKey, rNibErr := common.ValidateAndBuildRanLoadInformationKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetRanLoadInformationNotFoundFailure - failed to validate key parameter") + } + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) + getNb, er := w.GetRanLoadInformation(name) + assert.NotNil(t, er) + assert.Nil(t, getNb) + assert.Equal(t, 1, er.GetCode()) + assert.EqualValues(t, "1 RESOURCE_NOT_FOUND - #rNibReader.getByKeyAndUnmarshal - entity of type *entities.RanLoadInformation not found. Key: LOAD:name", er.Error()) +} + +func TestGetRanLoadInformationUnmarshalFailure(t *testing.T) { + name := "name" + readerPool = nil + sdlInstanceMock := initSdlInstanceMock(namespace, 1) + w := GetRNibReader() + var e error + ret := make(map[string]interface{}, 1) + redisKey, rNibErr := common.ValidateAndBuildRanLoadInformationKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetRanLoadInformationUnmarshalFailure - failed to validate key parameter") + } + ret[redisKey] = "data" + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) + getNb, er := w.GetRanLoadInformation(name) + assert.NotNil(t, er) + assert.Nil(t, getNb) + assert.Equal(t, 2, er.GetCode()) + assert.EqualValues(t, "2 INTERNAL_ERROR - proto: can't skip unknown wire type 4", er.Error()) +} + +func TestGetRanLoadInformationSdlgoFailure(t *testing.T) { + name := "name" + errMsg := "expected Sdlgo error" + errMsgExpected := "2 INTERNAL_ERROR - expected Sdlgo error" + readerPool = nil + sdlInstanceMock := initSdlInstanceMock(namespace, 1) + w := GetRNibReader() + e := errors.New(errMsg) + var ret map[string]interface{} + redisKey, rNibErr := common.ValidateAndBuildRanLoadInformationKey(name) + if rNibErr != nil { + t.Errorf("#rNibReader_test.TestGetRanLoadInformationSdlgoFailure - failed to validate key parameter") + } + sdlInstanceMock.On("Get", []string{redisKey}).Return(ret, e) + getNb, er := w.GetRanLoadInformation(name) + assert.NotNil(t, er) + assert.Nil(t, getNb) + assert.Equal(t, 2, er.GetCode()) + assert.EqualValues(t, errMsgExpected, er.Error()) +} + +func generateCellLoadInformation() *entities.CellLoadInformation { + cellLoadInformation := entities.CellLoadInformation{} + + cellLoadInformation.CellId = "123" + + ulInterferenceOverloadIndication := entities.UlInterferenceOverloadIndication_HIGH_INTERFERENCE + cellLoadInformation.UlInterferenceOverloadIndications = []entities.UlInterferenceOverloadIndication{ulInterferenceOverloadIndication} + + ulHighInterferenceInformation := entities.UlHighInterferenceInformation{ + TargetCellId:"456", + UlHighInterferenceIndication:"xxx", + } + + cellLoadInformation.UlHighInterferenceInfos = []*entities.UlHighInterferenceInformation{&ulHighInterferenceInformation } + + cellLoadInformation.RelativeNarrowbandTxPower = &entities.RelativeNarrowbandTxPower{ + RntpPerPrb:"xxx", + RntpThreshold:entities.RntpThreshold_NEG_4, + NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts_V1_ANT_PRT, + PB: 1, + PdcchInterferenceImpact:2, + EnhancedRntp: &entities.EnhancedRntp{ + EnhancedRntpBitmap:"xxx", + RntpHighPowerThreshold:entities.RntpThreshold_NEG_2, + EnhancedRntpStartTime: &entities.StartTime{StartSfn:500,StartSubframeNumber:5}, + }, + } + + cellLoadInformation.AbsInformation = &entities.AbsInformation{ + Mode: entities.AbsInformationMode_ABS_INFO_FDD, + AbsPatternInfo:"xxx", + NumberOfCellSpecificAntennaPorts:entities.NumberOfCellSpecificAntennaPorts_V2_ANT_PRT, + MeasurementSubset:"xxx", + } + + cellLoadInformation.InvokeIndication = entities.InvokeIndication_ABS_INFORMATION + + cellLoadInformation.ExtendedUlInterferenceOverloadInfo = &entities.ExtendedUlInterferenceOverloadInfo{ + AssociatedSubframes:"xxx", + ExtendedUlInterferenceOverloadIndications:cellLoadInformation.UlInterferenceOverloadIndications, + } + + compInformationItem := &entities.CompInformationItem{ + CompHypothesisSets: []*entities.CompHypothesisSet{&entities.CompHypothesisSet{CellId: "789", CompHypothesis:"xxx"}}, + BenefitMetric:50, + } + + cellLoadInformation.CompInformation = &entities.CompInformation{ + CompInformationItems:[]*entities.CompInformationItem{compInformationItem}, + CompInformationStartTime:&entities.StartTime{StartSfn:123,StartSubframeNumber:456}, + } + + cellLoadInformation.DynamicDlTransmissionInformation = &entities.DynamicDlTransmissionInformation{ + State: entities.NaicsState_NAICS_ACTIVE, + TransmissionModes:"xxx", + PB: 2, + PAList:[]entities.PA{entities.PA_DB_NEG_3}, + } + + return &cellLoadInformation +} + +func generateRanLoadInformation() *entities.RanLoadInformation { + ranLoadInformation := entities.RanLoadInformation{} + + ranLoadInformation.LoadTimestamp = uint64(time.Now().UnixNano()) + + cellLoadInformation := generateCellLoadInformation() + ranLoadInformation.CellLoadInfos = []*entities.CellLoadInformation{cellLoadInformation} + + return &ranLoadInformation +} + //integration tests //func TestGetEnbInteg(t *testing.T){ -- 2.16.6