Skip to content
Snippets Groups Projects
controller.go 3.46 KiB
Newer Older
  • Learn to ignore specific revisions
  • package gosdn
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"context"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"net"
    
    	"net/http"
    	"os"
    	"os/signal"
    
    	"syscall"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"github.com/google/uuid"
    	log "github.com/sirupsen/logrus"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"github.com/spf13/viper"
    	"google.golang.org/grpc"
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	pb "code.fbi.h-da.de/danet/api/go/gosdn/core"
    	cpb "code.fbi.h-da.de/danet/api/go/gosdn/csbi"
    	ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
    	spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound"
    	"code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
    	nbi "code.fbi.h-da.de/danet/gosdn/northbound/server"
    
    	"code.fbi.h-da.de/danet/gosdn/nucleus"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    var coreLock sync.RWMutex
    var coreOnce sync.Once
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // Core is the representation of the controller's core
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    type Core struct {
    
    	pndc       *nucleus.PndStore
    
    	httpServer *http.Server
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	grpcServer *grpc.Server
    	nbi        *nbi.NorthboundInterface
    
    	stopChan   chan os.Signal
    
    
    	csbiClient cpb.CsbiClient
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    }
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    var c *Core
    
    
    func init() {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	c = &Core{
    
    		pndc:     nucleus.NewPndStore(),
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		stopChan: make(chan os.Signal, 1),
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    
    	// Setting up signal capturing
    
    	signal.Notify(c.stopChan, os.Interrupt, syscall.SIGTERM)
    
    }
    
    // initialize does start-up housekeeping like reading controller config files
    func initialize() error {
    
    	if err := startGrpc(); err != nil {
    
    Martin Stiemerling's avatar
    Martin Stiemerling committed
    	}
    
    	coreLock.Lock()
    
    	startHttpServer()
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	coreLock.Unlock()
    
    
    	config := Config{}
    	err := config.InitializeConfig()
    	if err != nil {
    		return err
    	}
    
    	return createSouthboundInterfaces(config)
    
    func startGrpc() error {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	sock := viper.GetString("socket")
    	lis, err := net.Listen("tcp", sock)
    	if err != nil {
    		return err
    	}
    
    	log.Infof("listening to %v", lis.Addr())
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	c.grpcServer = grpc.NewServer()
    	c.nbi = nbi.NewNBI(c.pndc)
    	pb.RegisterCoreServer(c.grpcServer, c.nbi.Core)
    	ppb.RegisterPndServer(c.grpcServer, c.nbi.Pnd)
    
    	cpb.RegisterCsbiServer(c.grpcServer, c.nbi.Csbi)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	go func() {
    		if err := c.grpcServer.Serve(lis); err != nil {
    			log.Fatal(err)
    		}
    	}()
    
    
    	orchestrator := viper.GetString("csbi-orchestrator")
    	conn, err := grpc.Dial(orchestrator, grpc.WithInsecure())
    	c.csbiClient = cpb.NewCsbiClient(conn)
    
    	return nil
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    }
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // createSouthboundInterfaces initializes the controller with its supported SBIs
    
    func createSouthboundInterfaces(config Config) error {
    	sbi := nucleus.NewSBI(spb.Type(config.BaseSouthBoundType), config.BaseSouthBoundUUID)
    	return createPrincipalNetworkDomain(sbi, config)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    }
    
    // createPrincipalNetworkDomain initializes the controller with an initial PND
    
    func createPrincipalNetworkDomain(s southbound.SouthboundInterface, config Config) error {
    	pnd, err := nucleus.NewPND("base", "gosdn base pnd", config.BasePndUUID, s, c.csbiClient, callback)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    		return err
    	}
    
    	err = c.pndc.Add(pnd)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    
    // Run calls initialize to start the controller
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func Run(ctx context.Context) error {
    
    	var initError error
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	coreOnce.Do(func() {
    
    		initError = initialize()
    	})
    	if initError != nil {
    		log.WithFields(log.Fields{}).Error(initError)
    		return initError
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	log.WithFields(log.Fields{}).Info("initialisation finished")
    	for {
    		select {
    
    		case <-c.stopChan:
    			return shutdown()
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		case <-ctx.Done():
    
    			return shutdown()
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func shutdown() error {
    
    	log.Info("shutting down controller")
    
    	coreLock.Lock()
    	defer coreLock.Unlock()
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	c.grpcServer.GracefulStop()
    
    	return stopHttpServer()
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    }
    
    
    func callback(id uuid.UUID, ch chan nucleus.DeviceDetails) {
    	if ch != nil {
    		c.pndc.AddPendingChannel(id, ch)
    		log.Infof("pending channel %v added", id)
    	} else {
    		c.pndc.RemovePendingChannel(id)
    		log.Infof("pending channel %v removed", id)
    	}
    }