[SEBA-823] REST APIs initial implementation (legacy+new)

Change-Id: Ia8480b72540ff08d35003534d39aff984e31120c
diff --git a/cmd/bbsim/bbsim.go b/cmd/bbsim/bbsim.go
index 53b6ae0..d8cfcf0 100644
--- a/cmd/bbsim/bbsim.go
+++ b/cmd/bbsim/bbsim.go
@@ -17,23 +17,30 @@
 package main
 
 import (
+	"context"
+	"net"
+	"net/http"
+	"os"
+	"os/signal"
+	"runtime/pprof"
+	"sync"
+	"syscall"
+
+	"github.com/grpc-ecosystem/grpc-gateway/runtime"
 	"github.com/opencord/bbsim/api/bbsim"
+	"github.com/opencord/bbsim/api/legacy"
 	"github.com/opencord/bbsim/internal/bbsim/api"
 	"github.com/opencord/bbsim/internal/bbsim/devices"
 	"github.com/opencord/bbsim/internal/common"
 	log "github.com/sirupsen/logrus"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/reflection"
-	"net"
-	"os"
-	"runtime/pprof"
-	"sync"
 )
 
 func startApiServer(channel chan bool, group *sync.WaitGroup) {
 	// TODO make configurable
 	address := "0.0.0.0:50070"
-	log.Debugf("APIServer Listening on: %v", address)
+	log.Debugf("APIServer listening on: %v", address)
 	lis, err := net.Listen("tcp", address)
 	if err != nil {
 		log.Fatalf("APIServer failed to listen: %v", err)
@@ -43,25 +50,84 @@
 
 	reflection.Register(grpcServer)
 
-	wg := sync.WaitGroup{}
-	wg.Add(1)
-
 	go grpcServer.Serve(lis)
+	go startApiRestServer(channel, group, address)
 
-	for {
-		_, ok := <-channel
-		if !ok {
-			// if the olt channel is closed, stop the gRPC server
-			log.Warnf("Stopping API gRPC server")
-			grpcServer.Stop()
-			wg.Done()
-			break
-		}
+	select {
+	case <-channel:
+		// if the api channel is closed, stop the gRPC server
+		grpcServer.Stop()
+		log.Warnf("Stopping API gRPC server")
 	}
 
-	wg.Wait()
 	group.Done()
-	return
+}
+
+// startApiRestServer method starts the REST server (grpc gateway) for BBSim.
+func startApiRestServer(channel chan bool, group *sync.WaitGroup, grpcAddress string) {
+	ctx := context.Background()
+	ctx, cancel := context.WithCancel(ctx)
+	defer cancel()
+
+	// TODO make configurable
+	address := "0.0.0.0:50071"
+
+	mux := runtime.NewServeMux()
+	opts := []grpc.DialOption{grpc.WithInsecure()}
+
+	if err := bbsim.RegisterBBSimHandlerFromEndpoint(ctx, mux, grpcAddress, opts); err != nil {
+		log.Errorf("Could not register API server: %v", err)
+		return
+	}
+
+	s := &http.Server{Addr: address, Handler: mux}
+
+	go func() {
+		log.Infof("REST API server listening on %s ...", address)
+		if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+			log.Errorf("Could not start API server: %v", err)
+			return
+		}
+	}()
+
+	select {
+	case <-channel:
+		log.Warnf("Stopping API REST server")
+		s.Shutdown(ctx)
+	}
+
+	group.Done()
+}
+
+// This server aims to provide compatibility with the previous BBSim version. It is deprecated and will be removed in the future.
+func startLegacyApiServer(channel chan bool, group *sync.WaitGroup) {
+	// TODO make configurable
+	grpcAddress := "0.0.0.0:50072"
+	restAddress := "0.0.0.0:50073"
+
+	log.Debugf("Legacy APIServer listening on: %v", grpcAddress)
+	listener, err := net.Listen("tcp", grpcAddress)
+	if err != nil {
+		log.Fatalf("Legacy APIServer failed to listen: %v", err)
+		return
+	}
+	apiserver := grpc.NewServer()
+	legacy.RegisterBBSimServiceServer(apiserver, api.BBSimLegacyServer{})
+
+	go apiserver.Serve(listener)
+	// Start rest gateway for BBSim server
+	go api.StartRestGatewayService(channel, group, grpcAddress, restAddress)
+
+	select {
+	case <-channel:
+		// if the olt channel is closed, stop the gRPC server
+		log.Warnf("Stopping legacy API gRPC server")
+		apiserver.Stop()
+		break
+
+	}
+
+	group.Done()
 }
 
 func main() {
@@ -91,13 +157,26 @@
 	oltDoneChannel := make(chan bool)
 	apiDoneChannel := make(chan bool)
 
+	sigs := make(chan os.Signal, 1)
+	// stop API and OLT servers on SIGTERM
+	signal.Notify(sigs, syscall.SIGTERM)
+
+	go func() {
+		<-sigs
+		// TODO check when these servers should be shutdown
+		close(apiDoneChannel)
+		close(oltDoneChannel)
+	}()
+
 	wg := sync.WaitGroup{}
-	wg.Add(2)
+	wg.Add(5)
 
 	olt := devices.CreateOLT(options.OltID, options.NumNniPerOlt, options.NumPonPerOlt, options.NumOnuPerPon, options.STag, options.CTagInit, &oltDoneChannel, &apiDoneChannel, false)
 	go devices.StartOlt(olt, &wg)
 	log.Debugf("Created OLT with id: %d", options.OltID)
 	go startApiServer(apiDoneChannel, &wg)
+	go startLegacyApiServer(apiDoneChannel, &wg)
+
 	log.Debugf("Started APIService")
 
 	wg.Wait()