[RICPLT-2584] Implementation of E2TShutdownManager + Automation fix 71/2171/1
authorAmichai <amichai.sichel@intl.att.com>
Wed, 8 Jan 2020 14:45:07 +0000 (16:45 +0200)
committerAmichai <amichai.sichel@intl.att.com>
Wed, 8 Jan 2020 14:45:15 +0000 (16:45 +0200)
Change-Id: I1dbc4a1d14566c2ca9882ba603e3cf77458f54dc
Signed-off-by: Amichai <amichai.sichel@intl.att.com>
24 files changed:
Automation/Tests/KeepAlive/keep_alive_test.robot
Automation/Tests/Resource/Keywords.robot
Automation/Tests/Scripts/cleanup_db.py
E2Manager/app/main.go
E2Manager/clients/routing_manager_client.go
E2Manager/configuration/configuration.go
E2Manager/configuration/configuration_test.go
E2Manager/container-tag.yaml
E2Manager/go.mod
E2Manager/go.sum
E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go
E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go
E2Manager/managers/e2t_association_manager.go
E2Manager/managers/e2t_association_manager_test.go
E2Manager/managers/e2t_instances_manager.go
E2Manager/managers/e2t_instances_manager_test.go
E2Manager/managers/e2t_shutdown_manager.go
E2Manager/mocks/e2t_instances_manager_mock.go
E2Manager/mocks/rnibWriterMock.go
E2Manager/mocks/routing_manager_client_mock.go
E2Manager/rNibWriter/rNibWriter.go
E2Manager/rNibWriter/rNibWriter_test.go
E2Manager/resources/configuration.yaml
E2Manager/services/rnib_data_service.go

index ac226a2..1208b23 100644 (file)
@@ -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
index 1022890..eea1ce6 100644 (file)
@@ -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}
 
index 02c5f8f..5c8db84 100644 (file)
@@ -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
 
index 8eff30d..8c4dee2 100644 (file)
@@ -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)
 
index d4c9bbe..7679cca 100644 (file)
@@ -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)
 
index d37c497..06a8a11 100644 (file)
@@ -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
 }
 
index b83c661..bbd154d 100644 (file)
@@ -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) {
index 1827a37..3a7663b 100644 (file)
@@ -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
index 720727f..59a3fc9 100644 (file)
@@ -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
index eef93ff..ad692e7 100644 (file)
@@ -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=
index 7063f57..c75140f 100644 (file)
@@ -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
                }
index 9ca2452..1b7cba6 100644 (file)
@@ -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)}
index 9b0cada..9988d01 100644 (file)
@@ -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
+}
index fa13848..e8090f1 100644 (file)
@@ -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
index 1e12943..7f7c379 100644 (file)
@@ -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()
index 5c83954..7d48940 100644 (file)
@@ -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)
+}
index ddf3406..20e4554 100644 (file)
 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
+}
index 5919f9c..565f0bc 100644 (file)
@@ -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)
 }
 
index 5ca925f..9e1070e 100644 (file)
@@ -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)
+}
index fb1cafd..0652276 100644 (file)
@@ -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
index 13a31f3..a7195de 100644 (file)
@@ -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
 */
index 34ef4c8..6c8743e 100644 (file)
@@ -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){
index b70ddfc..6528db9 100644 (file)
@@ -14,3 +14,4 @@ maxRnibConnectionAttempts: 3
 rnibRetryIntervalMs: 10
 keepAliveResponseTimeoutMs: 4500
 keepAliveDelayMs: 1500
+e2tInstanceDeletionTimeoutMs: 15000
index 1a5af59..35b4c02 100644 (file)
@@ -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()