Copy latest code

Change-Id: Ibfcfce723adc532458911ec1df798fcd511fddaa
Signed-off-by: ss412g <shuky.har-noy@intl.att.com>
diff --git a/E2Manager/controllers/e2t_controller.go b/E2Manager/controllers/e2t_controller.go
new file mode 100644
index 0000000..2d95542
--- /dev/null
+++ b/E2Manager/controllers/e2t_controller.go
@@ -0,0 +1,121 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package controllers
+
+import (
+	"e2mgr/e2managererrors"
+	"e2mgr/logger"
+	"e2mgr/models"
+	"e2mgr/providers/httpmsghandlerprovider"
+	"encoding/json"
+	"net/http"
+	"net/http/httputil"
+	"strings"
+)
+
+type IE2TController interface {
+	GetE2TInstances(writer http.ResponseWriter, r *http.Request)
+}
+
+type E2TController struct {
+	logger          *logger.Logger
+	handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider
+}
+
+func NewE2TController(logger *logger.Logger, handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider) *E2TController {
+	return &E2TController{
+		logger:          logger,
+		handlerProvider: handlerProvider,
+	}
+}
+
+func (c *E2TController) GetE2TInstances(writer http.ResponseWriter, r *http.Request) {
+	c.logger.Infof("[Client -> E2 Manager] #E2TController.GetE2TInstances - request: %v", c.prettifyRequest(r))
+	c.handleRequest(writer, &r.Header, httpmsghandlerprovider.GetE2TInstancesRequest, nil, false)
+}
+
+func (c *E2TController) handleRequest(writer http.ResponseWriter, header *http.Header, requestName httpmsghandlerprovider.IncomingRequest, request models.Request, validateHeader bool) {
+
+	handler, err := c.handlerProvider.GetHandler(requestName)
+
+	if err != nil {
+		c.handleErrorResponse(err, writer)
+		return
+	}
+
+	response, err := handler.Handle(request)
+
+	if err != nil {
+		c.handleErrorResponse(err, writer)
+		return
+	}
+
+	if response == nil {
+		writer.WriteHeader(http.StatusNoContent)
+		c.logger.Infof("[E2 Manager -> Client] #E2TController.handleRequest - status response: %v", http.StatusNoContent)
+		return
+	}
+
+	result, err := response.Marshal()
+
+	if err != nil {
+		c.handleErrorResponse(err, writer)
+		return
+	}
+
+	c.logger.Infof("[E2 Manager -> Client] #E2TController.handleRequest - response: %s", result)
+	writer.Header().Set("Content-Type", "application/json")
+	writer.Write(result)
+}
+
+func (c *E2TController) handleErrorResponse(err error, writer http.ResponseWriter) {
+
+	var errorResponseDetails models.ErrorResponse
+	var httpError int
+
+	if err != nil {
+		switch err.(type) {
+		case *e2managererrors.RnibDbError:
+			e2Error, _ := err.(*e2managererrors.RnibDbError)
+			errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+			httpError = http.StatusInternalServerError
+		default:
+			e2Error := e2managererrors.NewInternalError()
+			errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+			httpError = http.StatusInternalServerError
+		}
+	}
+
+	errorResponse, _ := json.Marshal(errorResponseDetails)
+
+	c.logger.Errorf("[E2 Manager -> Client] #E2TController.handleErrorResponse - http status: %d, error response: %+v", httpError, errorResponseDetails)
+
+	writer.Header().Set("Content-Type", "application/json")
+	writer.WriteHeader(httpError)
+	_, err = writer.Write(errorResponse)
+
+	if err != nil {
+		c.logger.Errorf("#E2TController.handleErrorResponse - Cannot send response. writer:%v", writer)
+	}
+}
+
+func (c *E2TController) prettifyRequest(request *http.Request) string {
+	dump, _ := httputil.DumpRequest(request, true)
+	requestPrettyPrint := strings.Replace(string(dump), "\r\n", " ", -1)
+	return strings.Replace(requestPrettyPrint, "\n", "", -1)
+}
diff --git a/E2Manager/controllers/nodeb_controller.go b/E2Manager/controllers/nodeb_controller.go
index 912b4a9..cbfa7d6 100644
--- a/E2Manager/controllers/nodeb_controller.go
+++ b/E2Manager/controllers/nodeb_controller.go
@@ -176,7 +176,7 @@
 
 	c.logger.Infof("[E2 Manager -> Client] #NodebController.handleRequest - response: %s", result)
 	writer.Header().Set("Content-Type", "application/json")
-	writer.Write([]byte(result))
+	writer.Write(result)
 }
 
 func (c *NodebController) validateRequestHeader(header *http.Header) error {
@@ -228,7 +228,10 @@
 			e2Error, _ := err.(*e2managererrors.ResourceNotFoundError)
 			errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
 			httpError = http.StatusNotFound
-
+		case *e2managererrors.E2TInstanceAbsenceError:
+			e2Error, _ := err.(*e2managererrors.E2TInstanceAbsenceError)
+			errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+			httpError = http.StatusServiceUnavailable
 		default:
 			e2Error := e2managererrors.NewInternalError()
 			errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
diff --git a/E2Manager/controllers/nodeb_controller_test.go b/E2Manager/controllers/nodeb_controller_test.go
index 47b217b..f819138 100644
--- a/E2Manager/controllers/nodeb_controller_test.go
+++ b/E2Manager/controllers/nodeb_controller_test.go
@@ -30,7 +30,6 @@
 	"e2mgr/mocks"
 	"e2mgr/models"
 	"e2mgr/providers/httpmsghandlerprovider"
-	"e2mgr/rNibWriter"
 	"e2mgr/rmrCgo"
 	"e2mgr/services"
 	"e2mgr/services/rmrsender"
@@ -39,7 +38,6 @@
 	"fmt"
 	"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
 	"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-	"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
 	"github.com/gorilla/mux"
 	"github.com/pkg/errors"
 	"github.com/stretchr/testify/assert"
@@ -67,30 +65,27 @@
 	expectedJsonResponse string
 }
 
-func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock) {
+func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock) {
 	log := initLog(t)
 	config := configuration.ParseConfiguration()
 
 	rmrMessengerMock := &mocks.RmrMessengerMock{}
 	readerMock := &mocks.RnibReaderMock{}
-	readerProvider := func() reader.RNibReader {
-		return readerMock
-	}
+
 	writerMock := &mocks.RnibWriterMock{}
-	writerProvider := func() rNibWriter.RNibWriter {
-		return writerMock
-	}
-	rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
+
+	rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
 	rmrSender := getRmrSender(rmrMessengerMock, log)
 	ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
-	handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, rmrSender, config, rnibDataService, ranSetupManager)
+	e2tInstancesManager := &mocks.E2TInstancesManagerMock{}
+	handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, rmrSender, config, rnibDataService, ranSetupManager, e2tInstancesManager)
 	controller := NewNodebController(log, handlerProvider)
-	return controller, readerMock, writerMock, rmrMessengerMock
+	return controller, readerMock, writerMock, rmrMessengerMock, e2tInstancesManager
 }
 
 func TestX2SetupInvalidBody(t *testing.T) {
 
-	controller, _, _, _ := setupControllerTest(t)
+	controller, _, _, _, _ := setupControllerTest(t)
 
 	header := http.Header{}
 	header.Set("Content-Type", "application/json")
@@ -108,20 +103,23 @@
 
 func TestX2SetupSuccess(t *testing.T) {
 
-	controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
+	controller, readerMock, writerMock, rmrMessengerMock, _ := setupControllerTest(t)
 
 	ranName := "test"
-	nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+	nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
 	readerMock.On("GetNodeb", ranName).Return(nb, nil)
+	var nbUpdated = *nb
+	nbUpdated.ConnectionAttempts = 0
+	writerMock.On("UpdateNodebInfo", &nbUpdated).Return(nil)
 
-	var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-	writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
+	var nbUpdated2 = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
+	writerMock.On("UpdateNodebInfo", nbUpdated2).Return(nil)
 
 	payload := e2pdus.PackedX2setupRequest
-	xaction := []byte(ranName)
-	msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
+	var xAction []byte
+	msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction)
 
-	rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+	rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
 
 	header := http.Header{}
 	header.Set("Content-Type", "application/json")
@@ -134,22 +132,26 @@
 	assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
 }
 
+
 func TestEndcSetupSuccess(t *testing.T) {
 
-	controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
+	controller, readerMock, writerMock, rmrMessengerMock, _ := setupControllerTest(t)
 
 	ranName := "test"
-	nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
+	nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
 	readerMock.On("GetNodeb", ranName).Return(nb, nil)
+	var nbUpdated = *nb
+	nbUpdated.ConnectionAttempts = 0
+	writerMock.On("UpdateNodebInfo", &nbUpdated).Return(nil)
 
-	var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-	writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
+	var nbUpdated2 = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
+	writerMock.On("UpdateNodebInfo", nbUpdated2).Return(nil)
 
 	payload := e2pdus.PackedEndcX2setupRequest
-	xaction := []byte(ranName)
-	msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
+	var xAction[]byte
+	msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction)
 
-	rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+	rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
 
 	header := http.Header{}
 	header.Set("Content-Type", "application/json")
@@ -163,7 +165,7 @@
 }
 
 func TestShutdownHandlerRnibError(t *testing.T) {
-	controller, readerMock, _, _ := setupControllerTest(t)
+	controller, readerMock, _, _, _ := setupControllerTest(t)
 
 	rnibErr := &common.ResourceNotFoundError{}
 	var nbIdentityList []*entities.NbIdentity
@@ -180,7 +182,7 @@
 }
 
 func controllerGetNodebTestExecuter(t *testing.T, context *controllerGetNodebTestContext) {
-	controller, readerMock, _, _ := setupControllerTest(t)
+	controller, readerMock, _, _, _ := setupControllerTest(t)
 	writer := httptest.NewRecorder()
 	readerMock.On("GetNodeb", context.ranName).Return(context.nodebInfo, context.rnibError)
 	req, _ := http.NewRequest("GET", "/nodeb", nil)
@@ -192,7 +194,7 @@
 }
 
 func controllerGetNodebIdListTestExecuter(t *testing.T, context *controllerGetNodebIdListTestContext) {
-	controller, readerMock, _, _ := setupControllerTest(t)
+	controller, readerMock, _, _, _ := setupControllerTest(t)
 	writer := httptest.NewRecorder()
 	readerMock.On("GetListNodebIds").Return(context.nodebIdList, context.rnibError)
 	req, _ := http.NewRequest("GET", "/nodeb/ids", nil)
@@ -289,7 +291,7 @@
 }
 
 func TestHeaderValidationFailed(t *testing.T) {
-	controller, _, _, _ := setupControllerTest(t)
+	controller, _, _, _, _ := setupControllerTest(t)
 
 	writer := httptest.NewRecorder()
 
@@ -306,7 +308,7 @@
 }
 
 func TestShutdownStatusNoContent(t *testing.T) {
-	controller, readerMock, _, _ := setupControllerTest(t)
+	controller, readerMock, _, _, _ := setupControllerTest(t)
 
 	var rnibError error
 	nbIdentityList := []*entities.NbIdentity{}
@@ -319,7 +321,7 @@
 }
 
 func TestHandleInternalError(t *testing.T) {
-	controller, _, _, _ := setupControllerTest(t)
+	controller, _, _, _, _ := setupControllerTest(t)
 
 	writer := httptest.NewRecorder()
 	err := e2managererrors.NewInternalError()
@@ -333,7 +335,7 @@
 }
 
 func TestHandleCommandAlreadyInProgressError(t *testing.T) {
-	controller, _, _, _ := setupControllerTest(t)
+	controller, _, _, _, _ := setupControllerTest(t)
 	writer := httptest.NewRecorder()
 	err := e2managererrors.NewCommandAlreadyInProgressError()
 
@@ -345,8 +347,22 @@
 	assert.Equal(t, errorResponse.Message, err.Message)
 }
 
+func TestHandleE2TInstanceAbsenceError(t *testing.T) {
+	controller, _, _, _, _ := setupControllerTest(t)
+
+	writer := httptest.NewRecorder()
+	err := e2managererrors.NewE2TInstanceAbsenceError()
+
+	controller.handleErrorResponse(err, writer)
+	var errorResponse = parseJsonRequest(t, writer.Body)
+
+	assert.Equal(t, http.StatusServiceUnavailable, writer.Result().StatusCode)
+	assert.Equal(t, errorResponse.Code, err.Code)
+	assert.Equal(t, errorResponse.Message, err.Message)
+}
+
 func TestValidateHeaders(t *testing.T) {
-	controller, _, _, _ := setupControllerTest(t)
+	controller, _, _, _, _ := setupControllerTest(t)
 
 	header := http.Header{}
 	header.Set("Content-Type", "application/json")
@@ -376,12 +392,12 @@
 }
 
 func TestX2ResetHandleSuccessfulRequestedCause(t *testing.T) {
-	controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
+	controller, readerMock, _, rmrMessengerMock, _ := setupControllerTest(t)
 
 	ranName := "test1"
 	payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
-	xaction := []byte(ranName)
-	msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
+	var xAction []byte
+	msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction)
 	rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
 
 	writer := httptest.NewRecorder()
@@ -401,14 +417,14 @@
 }
 
 func TestX2ResetHandleSuccessfulRequestedDefault(t *testing.T) {
-	controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
+	controller, readerMock, _, rmrMessengerMock, _ := setupControllerTest(t)
 
 	ranName := "test1"
 	// o&m intervention
 	payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
-	xaction := []byte(ranName)
-	msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
-	rmrMessengerMock.On("SendMsg", msg).Return(msg, nil)
+	var xAction []byte
+	msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction)
+	rmrMessengerMock.On("SendMsg", msg, true).Return(msg, nil)
 
 	writer := httptest.NewRecorder()
 
@@ -426,7 +442,7 @@
 }
 
 func TestX2ResetHandleFailureInvalidBody(t *testing.T) {
-	controller, _, _, _ := setupControllerTest(t)
+	controller, _, _, _ , _:= setupControllerTest(t)
 
 	ranName := "test1"
 
@@ -443,7 +459,7 @@
 }
 
 func TestHandleErrorResponse(t *testing.T) {
-	controller, _, _, _ := setupControllerTest(t)
+	controller, _, _, _ , _:= setupControllerTest(t)
 
 	writer := httptest.NewRecorder()
 	controller.handleErrorResponse(e2managererrors.NewRnibDbError(), writer)
@@ -481,5 +497,5 @@
 func getRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
 	rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
 	rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-	return rmrsender.NewRmrSender(log, &rmrMessenger)
+	return rmrsender.NewRmrSender(log, rmrMessenger)
 }
diff --git a/E2Manager/controllers/root_controller_test.go b/E2Manager/controllers/root_controller_test.go
index 289e20b..42d0bdf 100644
--- a/E2Manager/controllers/root_controller_test.go
+++ b/E2Manager/controllers/root_controller_test.go
@@ -24,12 +24,10 @@
 	"e2mgr/configuration"
 	"e2mgr/logger"
 	"e2mgr/mocks"
-	"e2mgr/rNibWriter"
 	"e2mgr/services"
 	"fmt"
 	"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
 	"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-	"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
 	"github.com/stretchr/testify/assert"
 	"net"
 	"net/http"
@@ -44,13 +42,10 @@
 	}
 	config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 	readerMock := &mocks.RnibReaderMock{}
-	rnibReaderProvider := func() reader.RNibReader {
-		return readerMock
-	}
-	rnibWriterProvider := func() rNibWriter.RNibWriter {
-		return &mocks.RnibWriterMock{}
-	}
-	rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+
+	writerMock := &mocks.RnibWriterMock{}
+
+	rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
 	return rnibDataService, readerMock
 }