From: Amichai Date: Wed, 8 Jan 2020 14:45:07 +0000 (+0200) Subject: [RICPLT-2584] Implementation of E2TShutdownManager + Automation fix X-Git-Tag: R5_RC~129 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=f846c5987cd35da745534e26ac3a22bdcf8b030a;hp=63249264955a37429a64ebfec7028c6a487bdf1e;p=ric-plt%2Fe2mgr.git [RICPLT-2584] Implementation of E2TShutdownManager + Automation fix Change-Id: I1dbc4a1d14566c2ca9882ba603e3cf77458f54dc Signed-off-by: Amichai --- diff --git a/Automation/Tests/KeepAlive/keep_alive_test.robot b/Automation/Tests/KeepAlive/keep_alive_test.robot index ac226a2..1208b23 100644 --- a/Automation/Tests/KeepAlive/keep_alive_test.robot +++ b/Automation/Tests/KeepAlive/keep_alive_test.robot @@ -1,4 +1,4 @@ -############################################################################## +robot############################################################################## # # Copyright (c) 2019 AT&T Intellectual Property. # @@ -29,7 +29,7 @@ Library Collections Stop E2T stop_e2 - Sleep 1s + Sleep 3s Prepare logs for tests Remove log files diff --git a/Automation/Tests/Resource/Keywords.robot b/Automation/Tests/Resource/Keywords.robot index 1022890..eea1ce6 100644 --- a/Automation/Tests/Resource/Keywords.robot +++ b/Automation/Tests/Resource/Keywords.robot @@ -85,6 +85,7 @@ Prepare Simulator For Load Information 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(" ","-") @@ -114,7 +115,8 @@ Prepare Enviorment 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} @@ -125,6 +127,7 @@ Prepare Enviorment 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} diff --git a/Automation/Tests/Scripts/cleanup_db.py b/Automation/Tests/Scripts/cleanup_db.py index 02c5f8f..5c8db84 100644 --- a/Automation/Tests/Scripts/cleanup_db.py +++ b/Automation/Tests/Scripts/cleanup_db.py @@ -38,7 +38,7 @@ def flush(): 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 diff --git a/E2Manager/app/main.go b/E2Manager/app/main.go index 8eff30d..8c4dee2 100644 --- a/E2Manager/app/main.go +++ b/E2Manager/app/main.go @@ -60,10 +60,10 @@ func main() { 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) diff --git a/E2Manager/clients/routing_manager_client.go b/E2Manager/clients/routing_manager_client.go index d4c9bbe..7679cca 100644 --- a/E2Manager/clients/routing_manager_client.go +++ b/E2Manager/clients/routing_manager_client.go @@ -46,6 +46,7 @@ type IRoutingManagerClient interface { 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 { @@ -88,6 +89,11 @@ func (c *RoutingManagerClient) DissociateAllRans(e2tAddresses []string) error { 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) diff --git a/E2Manager/configuration/configuration.go b/E2Manager/configuration/configuration.go index d37c497..06a8a11 100644 --- a/E2Manager/configuration/configuration.go +++ b/E2Manager/configuration/configuration.go @@ -46,6 +46,7 @@ type Configuration struct { RnibRetryIntervalMs int KeepAliveResponseTimeoutMs int KeepAliveDelayMs int + E2TInstanceDeletionTimeoutMs int } func ParseConfiguration() *Configuration { @@ -72,6 +73,7 @@ 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 } diff --git a/E2Manager/configuration/configuration_test.go b/E2Manager/configuration/configuration_test.go index b83c661..bbd154d 100644 --- a/E2Manager/configuration/configuration_test.go +++ b/E2Manager/configuration/configuration_test.go @@ -38,6 +38,7 @@ func TestParseConfigurationSuccess(t *testing.T) { 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) { diff --git a/E2Manager/container-tag.yaml b/E2Manager/container-tag.yaml index 1827a37..3a7663b 100644 --- a/E2Manager/container-tag.yaml +++ b/E2Manager/container-tag.yaml @@ -1,4 +1,4 @@ # 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 diff --git a/E2Manager/go.mod b/E2Manager/go.mod index 720727f..59a3fc9 100644 --- a/E2Manager/go.mod +++ b/E2Manager/go.mod @@ -1,9 +1,9 @@ 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 diff --git a/E2Manager/go.sum b/E2Manager/go.sum index eef93ff..ad692e7 100644 --- a/E2Manager/go.sum +++ b/E2Manager/go.sum @@ -1,24 +1,18 @@ 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= @@ -110,11 +104,13 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf 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= @@ -160,6 +156,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 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= @@ -199,6 +196,7 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl 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= diff --git a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go index 7063f57..c75140f 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go @@ -89,7 +89,7 @@ func (h E2TermInitNotificationHandler) Handle(request *models.NotificationReques } if e2tInstance.State == entities.RoutingManagerFailure { - err := h.e2tInstancesManager.ActivateE2TInstance(e2tInstance) + err := h.e2tInstancesManager.SetE2tInstanceState(e2tAddress, e2tInstance.State, entities.Active) if err != nil { return } diff --git a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go index 9ca2452..1b7cba6 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go @@ -321,7 +321,7 @@ func TestE2TermInitHandlerSuccessOneRan_RoutingManagerFailure_Error(t *testing.T 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)} diff --git a/E2Manager/managers/e2t_association_manager.go b/E2Manager/managers/e2t_association_manager.go index 9b0cada..9988d01 100644 --- a/E2Manager/managers/e2t_association_manager.go +++ b/E2Manager/managers/e2t_association_manager.go @@ -100,3 +100,33 @@ func (m *E2TAssociationManager) DissociateRan(e2tAddress string, ranName string) } 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 +} diff --git a/E2Manager/managers/e2t_association_manager_test.go b/E2Manager/managers/e2t_association_manager_test.go index fa13848..e8090f1 100644 --- a/E2Manager/managers/e2t_association_manager_test.go +++ b/E2Manager/managers/e2t_association_manager_test.go @@ -282,4 +282,38 @@ func TestDissociateRanRoutingManagerError(t *testing.T) { 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 diff --git a/E2Manager/managers/e2t_instances_manager.go b/E2Manager/managers/e2t_instances_manager.go index 1e12943..7f7c379 100644 --- a/E2Manager/managers/e2t_instances_manager.go +++ b/E2Manager/managers/e2t_instances_manager.go @@ -43,13 +43,13 @@ type IE2TInstancesManager interface { 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 { @@ -270,9 +270,46 @@ func (m *E2TInstancesManager) RemoveRanFromInstance(ranName string, e2tAddress s 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() @@ -322,26 +359,6 @@ func (m *E2TInstancesManager) AddRanToInstance(ranName string, e2tAddress string 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() @@ -371,6 +388,38 @@ func (m *E2TInstancesManager) ResetKeepAliveTimestamp(e2tAddress string) error { 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() diff --git a/E2Manager/managers/e2t_instances_manager_test.go b/E2Manager/managers/e2t_instances_manager_test.go index 5c83954..7d48940 100644 --- a/E2Manager/managers/e2t_instances_manager_test.go +++ b/E2Manager/managers/e2t_instances_manager_test.go @@ -21,6 +21,7 @@ package managers import ( "e2mgr/configuration" + "e2mgr/e2managererrors" "e2mgr/logger" "e2mgr/mocks" "e2mgr/services" @@ -296,37 +297,38 @@ func TestSelectE2TInstancesSuccess(t *testing.T) { } 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") @@ -399,13 +401,6 @@ func TestResetKeepAliveTimestampRoutingManagerFailure(t *testing.T) { 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"))) @@ -460,3 +455,56 @@ func TestResetKeepAliveTimestampsForAllE2TInstancesSaveE2TInstanceFailure(t *tes 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) +} diff --git a/E2Manager/managers/e2t_shutdown_manager.go b/E2Manager/managers/e2t_shutdown_manager.go index ddf3406..20e4554 100644 --- a/E2Manager/managers/e2t_shutdown_manager.go +++ b/E2Manager/managers/e2t_shutdown_manager.go @@ -21,32 +21,174 @@ 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 +} diff --git a/E2Manager/mocks/e2t_instances_manager_mock.go b/E2Manager/mocks/e2t_instances_manager_mock.go index 5919f9c..565f0bc 100644 --- a/E2Manager/mocks/e2t_instances_manager_mock.go +++ b/E2Manager/mocks/e2t_instances_manager_mock.go @@ -40,8 +40,8 @@ func (m *E2TInstancesManagerMock) AddE2TInstance(e2tInstanceAddress string) erro 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) } @@ -55,6 +55,7 @@ func (m *E2TInstancesManagerMock) AddRanToInstance(ranName string, e2tAddress st return args.Error(0) } + func (m *E2TInstancesManagerMock) RemoveRanFromInstance(ranName string, e2tAddress string) error { args := m.Called(ranName, e2tAddress) return args.Error(0) @@ -79,8 +80,8 @@ func (m *E2TInstancesManagerMock) ResetKeepAliveTimestamp(e2tAddress string) err } -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) } diff --git a/E2Manager/mocks/rnibWriterMock.go b/E2Manager/mocks/rnibWriterMock.go index 5ca925f..9e1070e 100644 --- a/E2Manager/mocks/rnibWriterMock.go +++ b/E2Manager/mocks/rnibWriterMock.go @@ -76,3 +76,9 @@ func (rnibWriterMock *RnibWriterMock) SaveE2TAddresses(addresses []string) error return args.Error(0) } + +func (rnibWriterMock *RnibWriterMock) RemoveE2TInstance(address string) error { + args := rnibWriterMock.Called(address) + + return args.Error(0) +} diff --git a/E2Manager/mocks/routing_manager_client_mock.go b/E2Manager/mocks/routing_manager_client_mock.go index fb1cafd..0652276 100644 --- a/E2Manager/mocks/routing_manager_client_mock.go +++ b/E2Manager/mocks/routing_manager_client_mock.go @@ -49,4 +49,10 @@ func (m *RoutingManagerClientMock) DissociateAllRans(e2tAddresses []string) erro 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 diff --git a/E2Manager/rNibWriter/rNibWriter.go b/E2Manager/rNibWriter/rNibWriter.go index 13a31f3..a7195de 100644 --- a/E2Manager/rNibWriter/rNibWriter.go +++ b/E2Manager/rNibWriter/rNibWriter.go @@ -43,6 +43,7 @@ type RNibWriter interface { SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error SaveE2TInstance(e2tInstance *entities.E2TInstance) error SaveE2TAddresses(addresses []string) error + RemoveE2TInstance(e2tAddress string) error } /* @@ -234,6 +235,20 @@ func (w *rNibWriterInstance) SaveE2TAddresses(addresses []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 */ diff --git a/E2Manager/rNibWriter/rNibWriter_test.go b/E2Manager/rNibWriter/rNibWriter_test.go index 34ef4c8..6c8743e 100644 --- a/E2Manager/rNibWriter/rNibWriter_test.go +++ b/E2Manager/rNibWriter/rNibWriter_test.go @@ -577,6 +577,39 @@ func TestSaveE2TAddressesSdlFailure(t *testing.T) { 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){ diff --git a/E2Manager/resources/configuration.yaml b/E2Manager/resources/configuration.yaml index b70ddfc..6528db9 100644 --- a/E2Manager/resources/configuration.yaml +++ b/E2Manager/resources/configuration.yaml @@ -14,3 +14,4 @@ maxRnibConnectionAttempts: 3 rnibRetryIntervalMs: 10 keepAliveResponseTimeoutMs: 4500 keepAliveDelayMs: 1500 +e2tInstanceDeletionTimeoutMs: 15000 diff --git a/E2Manager/services/rnib_data_service.go b/E2Manager/services/rnib_data_service.go index 1a5af59..35b4c02 100644 --- a/E2Manager/services/rnib_data_service.go +++ b/E2Manager/services/rnib_data_service.go @@ -47,6 +47,7 @@ type RNibDataService interface { GetE2TInstancesNoLogs(addresses []string) ([]*entities.E2TInstance, error) SaveE2TInstanceNoLogs(e2tInstance *entities.E2TInstance) error GetE2TAddressesNoLogs() ([]string, error) + RemoveE2TInstance(e2tAddress string) error } type rNibDataService struct { @@ -236,6 +237,17 @@ func (w *rNibDataService) SaveE2TAddresses(addresses []string) error { 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()