-##############################################################################
+robot##############################################################################
#
# Copyright (c) 2019 AT&T Intellectual Property.
#
Stop E2T
stop_e2
- Sleep 1s
+ Sleep 3s
Prepare logs for tests
Remove log files
Should Be Equal As Integers ${result[1]} ${docker_number}
Prepare Enviorment
+ Log To Console Starting preparations
${starting_timestamp} Evaluate datetime.datetime.now(datetime.timezone.utc).isoformat("T") modules=datetime
${e2t_log_filename} Evaluate "e2t.${SUITE NAME}.log".replace(" ","-")
${e2mgr_log_filename} Evaluate "e2mgr.${SUITE NAME}.log".replace(" ","-")
Set Suite Variable ${Save_e2e_simu_log}
Set Suite Variable ${Save_rm_sim_log}
Set Suite Variable ${Save_e2adapter_log}
-
+
+ Log To Console Ready to flush db
${flush} cleanup_db.flush
Should Be Equal As Strings ${flush} True
Run And Return Rc And Output ${stop_simu}
Run And Return Rc And Output ${run_e2e_simu_regular}
Run And Return Rc And Output ${restart_e2adapter}
Sleep 3s
+ Log To Console Validating dockers are up
${result}= Run And Return Rc And Output ${docker_command}
Should Be Equal As Integers ${result[1]} ${docker_number}
r.set("{e2Manager},E2TAddresses", "[\"e2t.att.com:38000\"]")
- r.set("{e2Manager},E2TInstance:e2t.att.com:38000", "{\"address\":\"e2t.att.com:38000\",\"associatedRanList\":[],\"keepAliveTimestamp\":" + str(int(time.time())) + ",\"state\":\"ACTIVE\"}")
+ r.set("{e2Manager},E2TInstance:e2t.att.com:38000", "{\"address\":\"e2t.att.com:38000\",\"associatedRanList\":[],\"keepAliveTimestamp\":" + str(int((time.time()+2) * 1000000000)) + ",\"state\":\"ACTIVE\"}")
return True
rmrSender := rmrsender.NewRmrSender(logger, rmrMessenger)
ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
- e2tShutdownManager := managers.NewE2TShutdownManager(logger, rnibDataService, e2tInstancesManager)
- e2tKeepAliveWorker := managers.NewE2TKeepAliveWorker(logger, rmrSender, e2tInstancesManager, e2tShutdownManager, config)
routingManagerClient := clients.NewRoutingManagerClient(logger, config, &http.Client{})
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient)
+ e2tShutdownManager := managers.NewE2TShutdownManager(logger, config, rnibDataService, e2tInstancesManager, e2tAssociationManager, ranSetupManager)
+ e2tKeepAliveWorker := managers.NewE2TKeepAliveWorker(logger, rmrSender, e2tInstancesManager, e2tShutdownManager, config)
rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider()
rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager)
AssociateRanToE2TInstance(e2tAddress string, ranName string) error
DissociateRanE2TInstance(e2tAddress string, ranName string) error
DissociateAllRans(e2tAddresses []string) error
+ DeleteE2TInstance(e2tAddress string, ransToBeDissociated []string, e2tToRansAssociations map[string][]string) error
}
func NewRoutingManagerClient(logger *logger.Logger, config *configuration.Configuration, httpClient HttpClient) *RoutingManagerClient {
return c.PostMessage(data, url)
}
+func (c *RoutingManagerClient) DeleteE2TInstance(e2tAddress string, ransToBeDissociated []string, e2tToRansAssociations map[string][]string) error {
+ //TODO - here should be the call to routing-manager...
+ return nil
+}
+
func (c *RoutingManagerClient) PostMessage(data interface{}, url string) error {
marshaled, err := json.Marshal(data)
RnibRetryIntervalMs int
KeepAliveResponseTimeoutMs int
KeepAliveDelayMs int
+ E2TInstanceDeletionTimeoutMs int
}
func ParseConfiguration() *Configuration {
config.RnibRetryIntervalMs = viper.GetInt("rnibRetryIntervalMs")
config.KeepAliveResponseTimeoutMs = viper.GetInt("keepAliveResponseTimeoutMs")
config.KeepAliveDelayMs = viper.GetInt("KeepAliveDelayMs")
+ config.E2TInstanceDeletionTimeoutMs = viper.GetInt("e2tInstanceDeletionTimeoutMs")
return &config
}
assert.Equal(t, 5, config.BigRedButtonTimeoutSec)
assert.Equal(t, 4500, config.KeepAliveResponseTimeoutMs)
assert.Equal(t, 1500, config.KeepAliveDelayMs)
+ assert.Equal(t, 15000, config.E2TInstanceDeletionTimeoutMs)
}
func TestParseConfigurationFileNotFoundFailure(t *testing.T) {
# The Jenkins job requires a tag to build the Docker image.
# Global-JJB script assumes this file is in the repo root.
---
-tag: 3.0.4.1
+tag: 3.0.5
module e2mgr
require (
- gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.28
- gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.28
- gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28
+ gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.29
+ gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.29
+ gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.29
gerrit.o-ran-sc.org/r/ric-plt/sdlgo v0.5.2
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.27 h1:frasTDcg8Q8FgYutzJ+xSLHz9YseR2BmPSSBs4GI/1M=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.27/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.28 h1:Rewapfbc30ZkBaYB/3gW3W1BEivoiPdQm5UnmUswcMA=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.28/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.27 h1:nvZDzuB/SYKDuF1It7M4/Y/iVlVrCZ0Ob8AITAyppKo=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.27/go.mod h1:Fh23KkroYw5CRBh39WzZzxpKSkpQWL3scdzGnMngLo8=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.28 h1:+8Nn+Jn/AvhwBI1LtLsNS1PtOGAOYUHdicOrMn/8mmU=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.28/go.mod h1:Fh23KkroYw5CRBh39WzZzxpKSkpQWL3scdzGnMngLo8=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.27 h1:sWjlU/wBiWIBeSixnr9etCqtNmS2LW8jv+x2JGpf2eI=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.27/go.mod h1:vZ/335+rRSQW82wcbc80fNNICSK3TiCqIxmkqeC2Pfo=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28 h1:AaYvK59fxDXQUV9NCo6WuxDOvBQbnRU3WTPyJaYhkkg=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28/go.mod h1:vZ/335+rRSQW82wcbc80fNNICSK3TiCqIxmkqeC2Pfo=
-gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0 h1:+P3XuWKSaMbzh5PNtrW9gkZlCN0hKrZq+Cn8JetwBys=
-gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.29 h1:T0ydbEy2pmP2n8A/eyx5iF5PNm0XYa3A5G5HmXsN0Wo=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.29/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.29 h1:H/6CeGFUwS4S1DJ2OVwjt/qKmm/VTdgcgHcxBJfrQt4=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.29/go.mod h1:Fh23KkroYw5CRBh39WzZzxpKSkpQWL3scdzGnMngLo8=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.29 h1:eke+zU8y2gQmEBxAQryBXwBWwvXSHeu+pC11t8luQBQ=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.29/go.mod h1:EPOJ7YGXDS5F+IK1pa9cv2JYlj73PYOXVvgolhhCSfM=
gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2 h1:UK7awyRKIkVdokWvvkYvazlg3EWIfMnIqCcJxTnLlDA=
gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
go.uber.org/zap v1.11.0 h1:gSmpCfs+R47a4yQPAI4xJ0IPDLTRGXskm6UelqNXpqE=
go.uber.org/zap v1.11.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
}
if e2tInstance.State == entities.RoutingManagerFailure {
- err := h.e2tInstancesManager.ActivateE2TInstance(e2tInstance)
+ err := h.e2tInstancesManager.SetE2tInstanceState(e2tAddress, e2tInstance.State, entities.Active)
if err != nil {
return
}
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
- e2tInstancesManagerMock.On("ActivateE2TInstance", e2tInstance).Return(fmt.Errorf(" Error "))
+ e2tInstancesManagerMock.On("SetE2tInstanceState", e2tInstanceAddress, e2tInstance.State, entities.Active).Return(fmt.Errorf(" Error "))
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
}
return nil
}
+
+func (m *E2TAssociationManager) RemoveE2tInstance(e2tAddress string, ransToBeDissociated []string, ranAssociationList map[string][]string) error {
+
+ err := m.rmClient.DeleteE2TInstance(e2tAddress, ransToBeDissociated, ranAssociationList)
+ if err != nil {
+ m.logger.Errorf("#E2TAssociationManager.RemoveE2tInstance - RoutingManager failure: Failed to delete E2T %s. Error: %s", e2tAddress, err)
+ _ = m.setStateToRoutingManagerFailure(e2tAddress)
+ return err
+ }
+
+ err = m.e2tInstanceManager.RemoveE2TInstance(e2tAddress)
+ if err != nil {
+ m.logger.Errorf("#E2TAssociationManager.RemoveE2tInstance - Failed to remove E2T %s. Error: %s", e2tAddress, err)
+ return err
+ }
+
+ return nil
+}
+
+func (m *E2TAssociationManager) setStateToRoutingManagerFailure(e2tAddress string) error {
+ e2tInstance, err := m.e2tInstanceManager.GetE2TInstance(e2tAddress)
+ if err != nil {
+ return err
+ }
+ err = m.e2tInstanceManager.SetE2tInstanceState(e2tAddress, e2tInstance.State, entities.RoutingManagerFailure)
+ if err != nil {
+ return err
+ }
+ return nil
+}
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
httpClientMock.AssertExpectations(t)
+}
+
+func TestRemoveE2tInstanceSuccess(t *testing.T) {
+ manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
+ //mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
+
+ writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
+ e2tAddresses := []string{E2TAddress, E2TAddress2}
+ readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
+ e2tAddressesNew := []string{E2TAddress2}
+ writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
+
+ err := manager.RemoveE2tInstance(E2TAddress, []string{""}, make(map[string][]string))
+
+ assert.Nil(t, err)
+ readerMock.AssertExpectations(t)
+ writerMock.AssertExpectations(t)
+ httpClientMock.AssertExpectations(t)
+}
+
+func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) {
+ manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
+ //mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
+
+ writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
+ var e2tAddresses []string
+ readerMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError())
+
+ err := manager.RemoveE2tInstance(E2TAddress, []string{""}, make(map[string][]string))
+
+ assert.NotNil(t, err)
+ readerMock.AssertExpectations(t)
+ writerMock.AssertExpectations(t)
+ httpClientMock.AssertExpectations(t)
}
\ No newline at end of file
GetE2TInstances() ([]*entities.E2TInstance, error)
GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error)
AddE2TInstance(e2tAddress string) error
- RemoveE2TInstance(e2tInstance *entities.E2TInstance) error
+ RemoveE2TInstance(e2tAddress string) error
SelectE2TInstance() (string, error)
AddRanToInstance(ranName string, e2tAddress string) error
RemoveRanFromInstance(ranName string, e2tAddress string) error
- ActivateE2TInstance(e2tInstance *entities.E2TInstance) error
ResetKeepAliveTimestamp(e2tAddress string) error
ClearRansOfAllE2TInstances() error
+ SetE2tInstanceState(e2tAddress string, currentState entities.E2TInstanceState, newState entities.E2TInstanceState) error
}
func NewE2TInstancesManager(rnibDataService services.RNibDataService, logger *logger.Logger) *E2TInstancesManager {
return nil
}
-func (m *E2TInstancesManager) RemoveE2TInstance(e2tInstance *entities.E2TInstance) error {
+func (m *E2TInstancesManager) RemoveE2TInstance(e2tAddress string) error {
+ m.mux.Lock()
+ defer m.mux.Unlock()
+
+ err := m.rnibDataService.RemoveE2TInstance(e2tAddress)
+ if err != nil {
+ m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed removing E2TInstance. error: %s", e2tAddress, err)
+ return e2managererrors.NewRnibDbError()
+ }
+
+ e2tAddresses, err := m.rnibDataService.GetE2TAddresses()
+
+ if err != nil {
+ m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed retrieving E2T addresses list. error: %s", e2tAddress, err)
+ return e2managererrors.NewRnibDbError()
+ }
+
+ e2tAddresses = m.removeAddressFromList(e2tAddresses, e2tAddress)
+
+ err = m.rnibDataService.SaveE2TAddresses(e2tAddresses)
+ if err != nil {
+ m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed saving E2T addresses list. error: %s", e2tAddress, err)
+ return e2managererrors.NewRnibDbError()
+ }
+
return nil
}
+
+func (m *E2TInstancesManager) removeAddressFromList(e2tAddresses []string, addressToRemove string) []string {
+ newAddressList := []string{}
+
+ for _, address := range e2tAddresses {
+ if address != addressToRemove {
+ newAddressList = append(newAddressList, address)
+ }
+ }
+
+ return newAddressList
+}
+
func (m *E2TInstancesManager) SelectE2TInstance() (string, error) {
e2tInstances, err := m.GetE2TInstances()
return nil
}
-func (m E2TInstancesManager) ActivateE2TInstance(e2tInstance *entities.E2TInstance) error {
-
- if e2tInstance == nil {
- m.logger.Errorf("#E2TInstancesManager.ActivateE2TInstance - e2tInstance empty")
- return e2managererrors.NewInternalError()
- }
-
- m.logger.Infof("#E2TInstancesManager.ActivateE2TInstance - E2T Address: %s - activate E2T instance", e2tInstance.Address)
-
- e2tInstance.State = entities.Active
- e2tInstance.KeepAliveTimestamp = time.Now().UnixNano()
-
- err := m.rnibDataService.SaveE2TInstance(e2tInstance)
- if err != nil {
- m.logger.Errorf("#E2TInstancesManager.ActivateE2TInstance - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tInstance.Address, err)
- return err
- }
- return nil
-}
-
func (m *E2TInstancesManager) ResetKeepAliveTimestamp(e2tAddress string) error {
m.mux.Lock()
return nil
}
+func (m *E2TInstancesManager) SetE2tInstanceState(e2tAddress string, currentState entities.E2TInstanceState, newState entities.E2TInstanceState) error {
+ m.mux.Lock()
+ defer m.mux.Unlock()
+
+ e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress)
+
+ if err != nil {
+ m.logger.Errorf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err)
+ return e2managererrors.NewRnibDbError()
+ }
+
+ if (currentState != e2tInstance.State) {
+ m.logger.Warnf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Current state is not: %s", e2tAddress, currentState)
+ return e2managererrors.NewInternalError()
+ }
+
+ e2tInstance.State = newState
+ if (newState == entities.Active) {
+ e2tInstance.KeepAliveTimestamp = time.Now().UnixNano()
+ }
+
+ err = m.rnibDataService.SaveE2TInstance(e2tInstance)
+ if err != nil {
+ m.logger.Errorf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tInstance.Address, err)
+ return err
+ }
+
+ m.logger.Infof("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - State change: %s --> %s", e2tAddress, currentState, newState)
+
+ return nil
+}
+
func (m *E2TInstancesManager) ClearRansOfAllE2TInstances() error {
m.logger.Infof("#E2TInstancesManager.ClearRansOfAllE2TInstances - Going to clear associated RANs from E2T instances")
m.mux.Lock()
import (
"e2mgr/configuration"
+ "e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/mocks"
"e2mgr/services"
}
func TestActivateE2TInstanceSuccess(t *testing.T) {
- _, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+ rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
e2tInstance1 := entities.NewE2TInstance(E2TAddress)
e2tInstance1.State = entities.RoutingManagerFailure
e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
+ rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil)
+ rnibWriterMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.State == entities.Active })).Return(nil)
- rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
-
- err := e2tInstancesManager.ActivateE2TInstance(e2tInstance1)
+ err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.RoutingManagerFailure, entities.Active)
assert.Nil(t, err)
assert.Equal(t, entities.Active, e2tInstance1.State)
rnibWriterMock.AssertExpectations(t)
}
func TestActivateE2TInstance_RnibError(t *testing.T) {
- _, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
-
- e2tInstance1 := entities.NewE2TInstance(E2TAddress)
- e2tInstance1.State = entities.RoutingManagerFailure
- e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
+ rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
- rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
+ var e2tInstance1 *entities.E2TInstance
+ rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, common.NewInternalError(errors.New("for test")))
- err := e2tInstancesManager.ActivateE2TInstance(e2tInstance1)
+ err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.RoutingManagerFailure, entities.Active)
assert.NotNil(t, err)
+ rnibWriterMock.AssertExpectations(t)
}
func TestActivateE2TInstance_NoInstance(t *testing.T) {
- _, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+ rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
- err := e2tInstancesManager.ActivateE2TInstance(nil)
+ var e2tInstance1 *entities.E2TInstance
+ rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewResourceNotFoundError())
+
+ err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.RoutingManagerFailure, entities.Active)
assert.NotNil(t, err)
rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
}
-func TestRemoveE2TInstance(t *testing.T) {
- _, _, e2tInstancesManager := initE2TInstancesManagerTest(t)
- e2tInstance1 := entities.NewE2TInstance(E2TAddress)
- err := e2tInstancesManager.RemoveE2TInstance(e2tInstance1)
- assert.Nil(t, err)
-}
-
func TestResetKeepAliveTimestampsForAllE2TInstancesGetE2TInstancesFailure(t *testing.T) {
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
rnibReaderMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("Error")))
e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
rnibWriterMock.AssertNumberOfCalls(t, "SaveE2TInstance",1)
}
+
+func TestRemoveE2TInstanceSuccess(t *testing.T) {
+ rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+ rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
+ e2tAddresses := []string{E2TAddress, E2TAddress2}
+ rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
+ e2tAddressesNew := []string{E2TAddress2}
+ rnibWriterMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
+
+ err := e2tInstancesManager.RemoveE2TInstance(E2TAddress)
+ assert.Nil(t, err)
+ rnibReaderMock.AssertExpectations(t)
+ rnibWriterMock.AssertExpectations(t)
+}
+
+func TestRemoveE2TInstanceRnibErrorInRemoveInstance(t *testing.T) {
+ rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+ rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(e2managererrors.NewRnibDbError())
+
+ err := e2tInstancesManager.RemoveE2TInstance(E2TAddress)
+ assert.NotNil(t, err)
+ assert.IsType(t, e2managererrors.NewRnibDbError(), err)
+ rnibReaderMock.AssertExpectations(t)
+ rnibWriterMock.AssertExpectations(t)
+}
+
+func TestRemoveE2TInstanceRnibErrorInGetAddresses(t *testing.T) {
+ rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+ rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
+ var e2tAddresses []string
+ rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError())
+
+ err := e2tInstancesManager.RemoveE2TInstance(E2TAddress)
+ assert.NotNil(t, err)
+ assert.IsType(t, e2managererrors.NewRnibDbError(), err)
+ rnibReaderMock.AssertExpectations(t)
+ rnibWriterMock.AssertExpectations(t)
+}
+
+func TestRemoveE2TInstanceRnibErrorInSaveAddresses(t *testing.T) {
+ rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+ rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
+ e2tAddresses := []string{E2TAddress, E2TAddress2}
+ rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
+ e2tAddressesNew := []string{E2TAddress2}
+ rnibWriterMock.On("SaveE2TAddresses", e2tAddressesNew).Return(e2managererrors.NewRnibDbError())
+
+ err := e2tInstancesManager.RemoveE2TInstance(E2TAddress)
+ assert.NotNil(t, err)
+ assert.IsType(t, e2managererrors.NewRnibDbError(), err)
+ rnibReaderMock.AssertExpectations(t)
+ rnibWriterMock.AssertExpectations(t)
+}
package managers
import (
+ "e2mgr/configuration"
"e2mgr/logger"
"e2mgr/services"
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+ "time"
)
-
type IE2TShutdownManager interface {
Shutdown(e2tInstance *entities.E2TInstance) error
}
type E2TShutdownManager struct {
- logger *logger.Logger
- rnibDataService services.RNibDataService
- e2TInstancesManager IE2TInstancesManager
+ logger *logger.Logger
+ config *configuration.Configuration
+ rnibDataService services.RNibDataService
+ e2TInstancesManager IE2TInstancesManager
+ e2tAssociationManager *E2TAssociationManager
+ ranSetupManager IRanSetupManager
}
-func NewE2TShutdownManager(logger *logger.Logger, rnibDataService services.RNibDataService, e2TInstancesManager IE2TInstancesManager) E2TShutdownManager {
+func NewE2TShutdownManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, e2TInstancesManager IE2TInstancesManager, e2tAssociationManager *E2TAssociationManager, ranSetupManager IRanSetupManager) E2TShutdownManager {
return E2TShutdownManager{
- logger: logger,
- rnibDataService: rnibDataService,
- e2TInstancesManager: e2TInstancesManager,
+ logger: logger,
+ config: config,
+ rnibDataService: rnibDataService,
+ e2TInstancesManager: e2TInstancesManager,
+ e2tAssociationManager: e2tAssociationManager,
+ ranSetupManager: ranSetupManager,
}
}
-func (h E2TShutdownManager) Shutdown(e2tInstance *entities.E2TInstance) error{
- h.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s is Dead, RIP", e2tInstance.Address)
+func (m E2TShutdownManager) Shutdown(e2tInstance *entities.E2TInstance) error {
+ m.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s is Dead, RIP", e2tInstance.Address)
+
+ isE2tInstanceBeingDeleted := m.isE2tInstanceAlreadyBeingDeleted(e2tInstance)
+ if isE2tInstanceBeingDeleted {
+ m.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s is already being deleted", e2tInstance.Address)
+ return nil
+ }
+
+ err := m.markE2tInstanceToBeDeleted(e2tInstance)
+ if err != nil {
+ m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to mark E2T %s as 'ToBeDeleted'.", e2tInstance.Address)
+ return err
+ }
+
+ ranNamesToBeDissociated := []string{}
+ ranNamesToBeAssociated := make(map[string][]string) // e2tAddress -> associatedRanList
+
+ for _, ranName := range e2tInstance.AssociatedRanList {
+ err = m.reAssociateRanInMemory(ranName, ranNamesToBeAssociated, ranNamesToBeDissociated)
+ if err != nil {
+ m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to re-associate nodeb %s.", ranName)
+ return err
+ }
+ }
+
+ err = m.e2tAssociationManager.RemoveE2tInstance(e2tInstance.Address, ranNamesToBeDissociated, ranNamesToBeAssociated)
+ if err != nil {
+ m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to remove E2T %s.", e2tInstance.Address)
+ return err
+ }
+
+ err = m.clearNodebsAssociation(ranNamesToBeDissociated)
+ if err != nil {
+ m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to clear nodebs association to E2T %s.", e2tInstance.Address)
+ return err
+ }
+
+ err = m.reassociateNodebs(ranNamesToBeAssociated)
+ if err != nil {
+ m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to re-associate nodebs after killing E2T %s.", e2tInstance.Address)
+ return err
+ }
return nil
}
+
+func (m E2TShutdownManager) reassociateNodebs(ranNamesToBeAssociated map[string][]string) error {
+ for e2tAddress, ranNames := range ranNamesToBeAssociated {
+
+ err := m.associateAndSetupNodebs(ranNames, e2tAddress)
+ if err != nil {
+ return err
+ }
+
+ }
+ return nil
+}
+
+func (m E2TShutdownManager) clearNodebsAssociation(ranNamesToBeDissociated []string) error {
+ return m.associateAndSetupNodebs(ranNamesToBeDissociated, "")
+}
+
+func (m E2TShutdownManager) associateAndSetupNodebs(ranNamesToBeUpdated []string, e2tAddress string) error {
+ for _, ranName := range ranNamesToBeUpdated {
+ nodeb, err := m.rnibDataService.GetNodeb(ranName)
+ if err != nil {
+ m.logger.Warnf("#E2TShutdownManager.associateAndSetupNodebs - Failed to get nodeb %s from db.", ranName)
+ _, ok := err.(*common.ResourceNotFoundError)
+ if !ok {
+ continue
+ }
+ return err
+ }
+ nodeb.AssociatedE2TInstanceAddress = e2tAddress
+ err = m.rnibDataService.UpdateNodebInfo(nodeb)
+ if err != nil {
+ m.logger.Errorf("#E2TShutdownManager.associateAndSetupNodebs - Failed to save nodeb %s from db.", ranName)
+ return err
+ }
+
+ shouldSendSetup := len(e2tAddress) > 0
+ if shouldSendSetup {
+ err = m.ranSetupManager.ExecuteSetup(nodeb, entities.ConnectionStatus_CONNECTING)
+ if err != nil {
+ m.logger.Errorf("#E2TShutdownManager.associateAndSetupNodebs - Failed to execute Setup for nodeb %s.", ranName)
+ continue
+ }
+ }
+ }
+ return nil
+}
+
+func (m E2TShutdownManager) reAssociateRanInMemory(ranName string, ranNamesToBeAssociated map[string][]string, ranNamesToBeDissociated []string) error {
+ nodeb, err := m.rnibDataService.GetNodeb(ranName)
+ if err != nil {
+
+ _, ok := err.(*common.ResourceNotFoundError)
+
+ if !ok {
+ m.logger.Errorf("#E2TShutdownManager.reAssociateRanInMemory - Failed to get nodeb %s from db.", ranName)
+ return err
+ }
+
+ m.logger.Errorf("#E2TShutdownManager.reAssociateRanInMemory - nodeb %s not found in db. dissociating it...", ranName)
+ ranNamesToBeDissociated = append(ranNamesToBeDissociated, ranName)
+ return nil
+ }
+
+ if nodeb.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN || nodeb.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN {
+ m.logger.Errorf("#E2TShutdownManager.reAssociateRanInMemory - nodeb %s status is %s. dissociating it...", ranName, nodeb.ConnectionStatus)
+ ranNamesToBeDissociated = append(ranNamesToBeDissociated, ranName)
+ return nil
+ }
+
+ selectedE2tAddress, err := m.e2TInstancesManager.SelectE2TInstance()
+ if err != nil {
+ m.logger.Infof("#E2TShutdownManager.reAssociateRanInMemory - No selected E2T instance for nodeb %s found.", ranName)
+ ranNamesToBeDissociated = append(ranNamesToBeDissociated, ranName)
+ return nil
+ }
+
+ ranNamesToBeAssociated[selectedE2tAddress] = append(ranNamesToBeAssociated[selectedE2tAddress], ranName)
+ return nil
+}
+
+func (m E2TShutdownManager) markE2tInstanceToBeDeleted(e2tInstance *entities.E2TInstance) error {
+ e2tInstance.State = entities.ToBeDeleted
+ e2tInstance.DeletionTimestamp = time.Now().UnixNano()
+
+ return m.rnibDataService.SaveE2TInstance(e2tInstance)
+}
+
+func (m E2TShutdownManager) isE2tInstanceAlreadyBeingDeleted(e2tInstance *entities.E2TInstance) bool {
+ delta := time.Now().UnixNano() - e2tInstance.DeletionTimestamp
+ timestampNanosec := int64(time.Duration(m.config.E2TInstanceDeletionTimeoutMs) * time.Millisecond)
+
+ return delta <= timestampNanosec
+}
return args.Error(0)
}
-func (m *E2TInstancesManagerMock) RemoveE2TInstance(e2tInstance *entities.E2TInstance) error {
- args := m.Called(e2tInstance)
+func (m *E2TInstancesManagerMock) RemoveE2TInstance(e2tAddress string) error {
+ args := m.Called(e2tAddress)
return args.Error(0)
}
return args.Error(0)
}
+
func (m *E2TInstancesManagerMock) RemoveRanFromInstance(ranName string, e2tAddress string) error {
args := m.Called(ranName, e2tAddress)
return args.Error(0)
}
-func (m *E2TInstancesManagerMock) ActivateE2TInstance(e2tInstance *entities.E2TInstance) error {
- args := m.Called(e2tInstance)
+func (m *E2TInstancesManagerMock) SetE2tInstanceState(e2tAddress string, currentState entities.E2TInstanceState, newState entities.E2TInstanceState) error {
+ args := m.Called(e2tAddress, currentState, newState)
return args.Error(0)
}
return args.Error(0)
}
+
+func (rnibWriterMock *RnibWriterMock) RemoveE2TInstance(address string) error {
+ args := rnibWriterMock.Called(address)
+
+ return args.Error(0)
+}
args := m.Called(e2tAddresses)
return args.Error(0)
+}
+
+func (m *RoutingManagerClientMock) DeleteE2TInstance(e2tAddress string, ransToBeDissociated []string, e2tToRansAssociations map[string][]string) error {
+
+ args := m.Called(e2tAddress, ransToBeDissociated, e2tToRansAssociations)
+ return args.Error(0)
}
\ No newline at end of file
SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error
SaveE2TInstance(e2tInstance *entities.E2TInstance) error
SaveE2TAddresses(addresses []string) error
+ RemoveE2TInstance(e2tAddress string) error
}
/*
return nil
}
+
+func (w *rNibWriterInstance) RemoveE2TInstance(address string) error {
+ key, rNibErr := common.ValidateAndBuildE2TInstanceKey(address)
+ if rNibErr != nil {
+ return rNibErr
+ }
+ err := w.sdl.Remove([]string{key})
+
+ if err != nil {
+ return common.NewInternalError(err)
+ }
+ return nil
+}
+
/*
Close the writer
*/
assert.IsType(t, &common.InternalError{}, rNibErr)
}
+func TestRemoveE2TInstanceSuccess(t *testing.T) {
+ address := "10.10.2.15:9800"
+ w, sdlInstanceMock := initSdlInstanceMock(namespace)
+
+ e2tAddresses := []string{fmt.Sprintf("E2TInstance:%s", address)}
+ var e error
+ sdlInstanceMock.On("Remove", e2tAddresses).Return(e)
+
+ rNibErr := w.RemoveE2TInstance(address)
+ assert.Nil(t, rNibErr)
+ sdlInstanceMock.AssertExpectations(t)
+}
+
+func TestRemoveE2TInstanceSdlFailure(t *testing.T) {
+ address := "10.10.2.15:9800"
+ w, sdlInstanceMock := initSdlInstanceMock(namespace)
+
+ e2tAddresses := []string{fmt.Sprintf("E2TInstance:%s", address)}
+ expectedErr := errors.New("expected error")
+ sdlInstanceMock.On("Remove", e2tAddresses).Return(expectedErr)
+
+ rNibErr := w.RemoveE2TInstance(address)
+ assert.IsType(t, &common.InternalError{}, rNibErr)
+}
+
+func TestRemoveE2TInstanceEmptyAddressFailure(t *testing.T) {
+ w, sdlInstanceMock := initSdlInstanceMock(namespace)
+
+ rNibErr := w.RemoveE2TInstance("")
+ assert.IsType(t, &common.ValidationError{}, rNibErr)
+ sdlInstanceMock.AssertExpectations(t)
+}
+
//Integration tests
//
//func TestSaveEnbGnbInteg(t *testing.T){
rnibRetryIntervalMs: 10
keepAliveResponseTimeoutMs: 4500
keepAliveDelayMs: 1500
+e2tInstanceDeletionTimeoutMs: 15000
GetE2TInstancesNoLogs(addresses []string) ([]*entities.E2TInstance, error)
SaveE2TInstanceNoLogs(e2tInstance *entities.E2TInstance) error
GetE2TAddressesNoLogs() ([]string, error)
+ RemoveE2TInstance(e2tAddress string) error
}
type rNibDataService struct {
return err
}
+func (w *rNibDataService) RemoveE2TInstance(e2tAddress string) error {
+ w.logger.Infof("#RnibDataService.RemoveE2TInstance - e2tAddress: %s", e2tAddress)
+
+ err := w.retry("RemoveE2TInstance", func() (err error) {
+ err = w.rnibWriter.RemoveE2TInstance(e2tAddress)
+ return
+ })
+
+ return err
+}
+
func (w *rNibDataService) PingRnib() bool {
err := w.retry("GetListNodebIds", func() (err error) {
_, err = w.rnibReader.GetListNodebIds()