Skip to content
Snippets Groups Projects
commands.go 5.33 KiB
Newer Older
  • Learn to ignore specific revisions
  • Malte Bauch's avatar
    Malte Bauch committed
    package commands
    
    import (
    	"context"
    
    Malte Bauch's avatar
    Malte Bauch committed
    	"time"
    
    	pb "code.fbi.h-da.de/cocsn/gosdn/api/proto"
    	"code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/app"
    
    	"github.com/rivo/tview"
    
    Malte Bauch's avatar
    Malte Bauch committed
    	grpc "google.golang.org/grpc"
    
    Malte Bauch's avatar
    Malte Bauch committed
    	//Package google.golang.org/grpc/health is needed to make gRPC Health Check work
    	_ "google.golang.org/grpc/health"
    	healthpb "google.golang.org/grpc/health/grpc_health_v1"
    
    	"google.golang.org/protobuf/types/known/emptypb"
    
    Malte Bauch's avatar
    Malte Bauch committed
    )
    
    const (
    	defaultName = "gosdn-cli"
    )
    
    type command struct {
    	Name        string
    	Description string
    
    	Function    func(conn *grpc.ClientConn) string
    
    //CommandList contains the specific goSDN gRPC calls
    
    Malte Bauch's avatar
    Malte Bauch committed
    var CommandList = []command{
    
    	{"hello", "test connection to controller", goSDNSayHello},
    
    Malte Bauch's avatar
    Malte Bauch committed
    	{"testdb", "test all database connections", goSDNTestDB},
    
    	{"tapiGetDevices", "creates devices", TAPIGetEdge},
    	{"tapiGetInterfaces", "creates interfaces", TAPIGetEdgeNode},
    	{"tapiGetLinks", "creates links between devices", TAPIGetLink},
    	{"shutdown", "request controller to shutdown", goSDNShutdown},
    
    Malte Bauch's avatar
    Malte Bauch committed
    var serviceConfig = `{
    	"loadBalancingPolicy": "round_robin",
    	"healthCheckConfig": {
    		"serviceName": ""
    	}
    }`
    
    
    //Connect creates a new connection to the gRPC server
    
    func Connect(address string) (*grpc.ClientConn, error) {
    
    Malte Bauch's avatar
    Malte Bauch committed
    	options := []grpc.DialOption{
    		grpc.WithInsecure(),
    		grpc.WithBlock(),
    		grpc.WithDefaultServiceConfig(serviceConfig),
    		grpc.WithTimeout(5 * time.Second),
    	}
    
    	return grpc.Dial(address, options...)
    
    Malte Bauch's avatar
    Malte Bauch committed
    //GoSDNLogStream creates a continuous gRPC stream to recieve goSDN logs
    
    Malte Bauch's avatar
    Malte Bauch committed
    func GoSDNLogStream(app *app.App, conn *grpc.ClientConn, tv *tview.TextView) error {
    
    	var streamError error
    	c := pb.NewGrpcCliClient(conn)
    	stream, err := c.CreateLogStream(context.Background(), &emptypb.Empty{})
    	if err != nil {
    
    Malte Bauch's avatar
    Malte Bauch committed
    		return err
    
    	}
    
    	go func(stream pb.GrpcCli_CreateLogStreamClient) {
    		for {
    			msg, err := stream.Recv()
    			if err != nil {
    				streamError = err
    
    Malte Bauch's avatar
    Malte Bauch committed
    
    				go func() {
    					ticker := time.NewTicker(5 * time.Second)
    					for range ticker.C {
    						if err := GoSDNLogStream(app, conn, tv); err == nil {
    							ticker.Stop()
    							return
    						}
    					}
    				}()
    
    
    			response := []byte(msg.Log)
    
    Malte Bauch's avatar
    Malte Bauch committed
    			app.QueueUpdateDraw(func() {
    				tv.Write(response)
    			})
    
    func goSDNSayHello(conn *grpc.ClientConn) string {
    
    Malte Bauch's avatar
    Malte Bauch committed
    	c := pb.NewGrpcCliClient(conn)
    
    	// Contact the server and print out its response.
    	name := defaultName
    	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    	defer cancel()
    	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
    	if err != nil {
    
    Malte Bauch's avatar
    Malte Bauch committed
    		return err.Error()
    
    	return r.GetMessage()
    
    Malte Bauch's avatar
    Malte Bauch committed
    //WatchHealth continuous gRPC Health Check stream to recieve health changes
    func WatchHealth(service string, app *app.App, conn *grpc.ClientConn, tv *tview.TextView) error {
    	var streamError error
    
    	c := healthpb.NewHealthClient(conn)
    	stream, err := c.Watch(context.Background(), &healthpb.HealthCheckRequest{Service: service})
    	if err != nil {
    		app.QueueUpdateDraw(func() {
    			tv.Clear()
    			tv.SetText(err.Error())
    		})
    		return err
    	}
    
    	go func(stream healthpb.Health_WatchClient) {
    		for {
    			msg, err := stream.Recv()
    			if err != nil {
    				streamError = err
    				go func() {
    					ticker := time.NewTicker(5 * time.Second)
    					for range ticker.C {
    						if err := WatchHealth(service, app, conn, tv); err == nil {
    							ticker.Stop()
    							return
    						}
    					}
    				}()
    
    				break
    			}
    
    			app.QueueUpdateDraw(func() {
    				tv.Clear()
    				tv.SetText(msg.GetStatus().String())
    			})
    
    		}
    	}(stream)
    
    	return streamError
    }
    
    
    func goSDNShutdown(conn *grpc.ClientConn) string {
    
    Malte Bauch's avatar
    Malte Bauch committed
    
    	c := pb.NewGrpcCliClient(conn)
    
    	// Contact the server and print out its response.
    	name := defaultName
    	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    	defer cancel()
    	r, err := c.Shutdown(ctx, &pb.ShutdownRequest{Name: name})
    	if err != nil {
    
    Malte Bauch's avatar
    Malte Bauch committed
    		return err.Error()
    
    	return r.GetMessage()
    
    func goSDNTestDB(conn *grpc.ClientConn) string {
    
    Malte Bauch's avatar
    Malte Bauch committed
    	// TODO: fill with code and also see if grpc interface has this stub implemented.
    
    	return "not implemented yet"
    
    Malte Bauch's avatar
    Malte Bauch committed
    }
    
    // TAPIGetEdge triggers the GetEdge function of the Ciena
    // flavoured TAPI client
    
    func TAPIGetEdge(conn *grpc.ClientConn) string {
    
    Malte Bauch's avatar
    Malte Bauch committed
    
    	c := pb.NewGrpcCliClient(conn)
    
    	// Contact the server and print out its response.
    	name := defaultName
    	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    	defer cancel()
    	r, err := c.TAPIGetEdge(ctx, &pb.TAPIRequest{Name: name})
    	if err != nil {
    
    Malte Bauch's avatar
    Malte Bauch committed
    		return err.Error()
    
    	return r.GetMessage()
    
    Malte Bauch's avatar
    Malte Bauch committed
    }
    
    // TAPIGetEdgeNode triggers the GetEdgeNode function of the Ciena
    // flavoured TAPI client
    
    func TAPIGetEdgeNode(conn *grpc.ClientConn) string {
    
    Malte Bauch's avatar
    Malte Bauch committed
    	c := pb.NewGrpcCliClient(conn)
    
    	// Contact the server and print out its response.
    	name := defaultName
    	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    	defer cancel()
    	r, err := c.TAPIGetEdgeNode(ctx, &pb.TAPIRequest{Name: name})
    	if err != nil {
    
    Malte Bauch's avatar
    Malte Bauch committed
    		return err.Error()
    
    	return r.GetMessage()
    
    Malte Bauch's avatar
    Malte Bauch committed
    }
    
    // TAPIGetLink triggers the GetLink function of the Ciena
    // flavoured TAPI client
    
    func TAPIGetLink(conn *grpc.ClientConn) string {
    
    Malte Bauch's avatar
    Malte Bauch committed
    
    	c := pb.NewGrpcCliClient(conn)
    
    	// Contact the server and print out its response.
    	name := defaultName
    	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    	defer cancel()
    	r, err := c.TAPIGetLink(ctx, &pb.TAPIRequest{Name: name})
    	if err != nil {
    
    Malte Bauch's avatar
    Malte Bauch committed
    		return err.Error()
    
    	return r.GetMessage()