Skip to content
Snippets Groups Projects
Commit 2d11812d authored by Manuel Kieweg's avatar Manuel Kieweg
Browse files

Merge branch '35-job-failed-185196' into 'develop'

Resolve "Job Failed #185196"

See merge request cocsn/gosdn!40
parents 13f6e7e4 6f6ea0f9
Branches
Tags
2 merge requests!40Resolve "Job Failed #185196",!18Develop
Pipeline #52643 passed
golangci-lint run\
--config .ci/.golangci-master.yml\
--out-format code-climate |\
jq -r '.[] | "\(.location.path):\(.location.lines.begin) \(.description)"'
\ No newline at end of file
...@@ -110,11 +110,14 @@ func (d Database) StorePND(pnd *PND) neo4j.Node { ...@@ -110,11 +110,14 @@ func (d Database) StorePND(pnd *PND) neo4j.Node {
//RemovePND removes the given principle network domain by id. //RemovePND removes the given principle network domain by id.
func (d Database) RemovePND(id string) {} func (d Database) RemovePND(id string) {}
//GetPNDByID gets a specific PND by the given ID.
func (d Database) GetPNDByID(id string) {} func (d Database) GetPNDByID(id string) {}
//GetNodesByLabel gets all nodes that belong to a specific label.
func (d Database) GetNodesByLabel(label string) {} func (d Database) GetNodesByLabel(label string) {}
func (d Database) GetDeviceByID(id string) {} //GetNodeByID gets a specific node by ID.
func (d Database) GetNodeByID(id string) {}
//storeNodesTxFunc transaction to store devices from a json. //storeNodesTxFunc transaction to store devices from a json.
//relates them to a specific pnd id. //relates them to a specific pnd id.
...@@ -345,7 +348,6 @@ func CreateLink() {} ...@@ -345,7 +348,6 @@ func CreateLink() {}
func RemoveLink() {} func RemoveLink() {}
//Shutdown closes the connection to the database //Shutdown closes the connection to the database
func (d Database) Shutdown() { func (d Database) Shutdown() error {
if err := d.driver.Close(); err != nil { return d.driver.Close()
}
} }
...@@ -2,30 +2,21 @@ package main ...@@ -2,30 +2,21 @@ package main
import ( import (
pb "code.fbi.h-da.de/cocsn/gosdn/cliInterface" pb "code.fbi.h-da.de/cocsn/gosdn/cliInterface"
"code.fbi.h-da.de/cocsn/gosdn/log"
"context" "context"
"flag" "flag"
"fmt" "fmt"
"github.com/rivo/tview"
"google.golang.org/grpc" "google.golang.org/grpc"
"log"
"os" "os"
"time" "time"
) )
const ( const (
address = "localhost:55055"
defaultName = "gosdn-cli" defaultName = "gosdn-cli"
) )
// Based on the helloworld example of grpc.io -- thx! // Based on the helloworld example of grpc.io -- thx!
const refreshInterval = 500 * time.Millisecond
var (
view *tview.Modal
app *tview.Application
)
type cliClientConfig struct { type cliClientConfig struct {
goSDNCLIAddr4 *string goSDNCLIAddr4 *string
goSDNCLIPort4 *int goSDNCLIPort4 *int
...@@ -40,12 +31,12 @@ type commandOptions struct { ...@@ -40,12 +31,12 @@ type commandOptions struct {
} }
var commandList = map[string]commandOptions{ var commandList = map[string]commandOptions{
"hello": {"hello", "test connection to goSDN controller", goSDNSayHello}, "hello": {"hello", "test connection to goSDN controller", goSDNSayHello},
"shutdown": {"shutdown", "request goSDN controller to shutdown", goSDNShutdown}, "shutdown": {"shutdown", "request goSDN controller to shutdown", goSDNShutdown},
"testdb" : {"testdb", "test all database connections", goSDNTestDB}, "testdb": {"testdb", "test all database connections", goSDNTestDB},
"tapigetedge" : {"tapigetedge", "get list of edges", TAPIGetEdge}, "tapigetedge": {"tapigetedge", "get list of edges", TAPIGetEdge},
"tapigetedgenode" : {"tapigetedgenode", "get list of edgenodes", TAPIGetEdgeNode}, "tapigetedgenode": {"tapigetedgenode", "get list of edgenodes", TAPIGetEdgeNode},
"tapigetlink" : {"tapigetlink", "get list of links", TAPIGetLink}, "tapigetlink": {"tapigetlink", "get list of links", TAPIGetLink},
} }
/* /*
...@@ -67,61 +58,49 @@ func main() { ...@@ -67,61 +58,49 @@ func main() {
flag.Parse() flag.Parse()
// Print complete command list and exit // Print complete command list and exit
if *printCommandList == true { if *printCommandList {
for _, element := range commandList { for _, element := range commandList {
fmt.Println(element.name + "\t" + element.description) fmt.Println(element.name + "\t" + element.description)
} }
os.Exit(0) os.Exit(0)
} }
log.Println("Starting " + defaultName + " to access the goSDN controller") log.Info("Starting " + defaultName + " to access the goSDN controller")
// Prepare string with socket for connection to the goSDN controller // Prepare string with socket for connection to the goSDN controller
goSDNSocketAddress := fmt.Sprintf("%s:%d", *myConfiguration.goSDNCLIAddr4, *myConfiguration.goSDNCLIPort4) goSDNSocketAddress := fmt.Sprintf("%s:%d", *myConfiguration.goSDNCLIAddr4, *myConfiguration.goSDNCLIPort4)
log.Println("Connecting to the goSDN server at: " + goSDNSocketAddress) log.Info("Connecting to the goSDN server at: " + goSDNSocketAddress)
// Set up a connection to the server. // Set up a connection to the server.
address := "localhost:55055" address := "localhost:55055"
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
if err != nil { if err != nil {
log.Fatalf("did not connect: %v", err) log.Fatal(err)
} }
defer conn.Close() defer conn.Close()
log.Println(("Connected to " + conn.Target())) log.Info("Connected to " + conn.Target())
// Check for non-interactive or interactive mode // Check for non-interactive or interactive mode
if *myConfiguration.interactive == false { if !*myConfiguration.interactive {
log.Println("starting in non-interactive mode") log.Info("starting in non-interactive mode")
// Lookup command or die // Lookup command or die
_, found := commandList[*myConfiguration.goSDNCommand] _, found := commandList[*myConfiguration.goSDNCommand]
if found { if found {
// Excecute desired command // Excecute desired command
commandList[*myConfiguration.goSDNCommand].command(conn) commandList[*myConfiguration.goSDNCommand].command(conn)
} else { } else {
log.Fatalf("Your desired command %s is not available", commandList[*myConfiguration.goSDNCommand].name) // TODO: change once gosdn/errors exist
log.Fatal("Your desired command is not available: ", commandList[*myConfiguration.goSDNCommand].name)
os.Exit(1) os.Exit(1)
} }
} else { } else {
log.Println("starting in interactive mode -- do not use yet") log.Info("starting in interactive mode -- do not use yet")
os.Exit(1) os.Exit(1)
app = tview.NewApplication().EnableMouse(true)
flex := tview.NewFlex().
AddItem(tview.NewBox().SetBorder(true).SetTitle("Command List"), 0, 1, false).
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(tview.NewBox().SetBorder(true).SetTitle("Top"), 0, 1, false).
AddItem(tview.NewBox().SetBorder(true).SetTitle("Middle (3 x height of Top)"), 0, 3, false).
AddItem(tview.NewBox().SetBorder(true).SetTitle("Bottom (5 rows)"), 5, 1, false), 0, 2, false)
if err := app.SetRoot(flex, true).Run(); err != nil {
panic(err)
}
} }
} }
func goSDNSayHello (conn *grpc.ClientConn) { func goSDNSayHello(conn *grpc.ClientConn) {
c := pb.NewGrpcCliClient(conn) c := pb.NewGrpcCliClient(conn)
// Contact the server and print out its response. // Contact the server and print out its response.
...@@ -133,9 +112,9 @@ func goSDNSayHello (conn *grpc.ClientConn) { ...@@ -133,9 +112,9 @@ func goSDNSayHello (conn *grpc.ClientConn) {
defer cancel() defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name}) r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
if err != nil { if err != nil {
log.Fatalf("could not say hello: %v", err) log.Fatal(err)
} }
log.Printf("Greeting: %s", r.String()) log.Info("Greeting: ", r.String())
} }
...@@ -152,16 +131,17 @@ func goSDNShutdown(conn *grpc.ClientConn) { ...@@ -152,16 +131,17 @@ func goSDNShutdown(conn *grpc.ClientConn) {
defer cancel() defer cancel()
r, err := c.Shutdown(ctx, &pb.ShutdownRequest{Name: name}) r, err := c.Shutdown(ctx, &pb.ShutdownRequest{Name: name})
if err != nil { if err != nil {
log.Fatalf("could not request shutdown: %v", err) log.Fatal(err)
} }
log.Printf("Greeting: %s", r.GetMessage()) log.Info("Greeting: ", r.GetMessage())
} }
func goSDNTestDB(conn *grpc.ClientConn) { func goSDNTestDB(conn *grpc.ClientConn) {
// TODO: fill with code and also see if grpc interface has this stub implemented. // TODO: fill with code and also see if grpc interface has this stub implemented.
} }
// TAPIGetEdge triggers the GetEdge function of the Ciena
// flavoured TAPI client
func TAPIGetEdge(conn *grpc.ClientConn) { func TAPIGetEdge(conn *grpc.ClientConn) {
c := pb.NewGrpcCliClient(conn) c := pb.NewGrpcCliClient(conn)
...@@ -175,11 +155,13 @@ func TAPIGetEdge(conn *grpc.ClientConn) { ...@@ -175,11 +155,13 @@ func TAPIGetEdge(conn *grpc.ClientConn) {
defer cancel() defer cancel()
r, err := c.TAPIGetEdge(ctx, &pb.TAPIRequest{Name: name}) r, err := c.TAPIGetEdge(ctx, &pb.TAPIRequest{Name: name})
if err != nil { if err != nil {
log.Fatalf("could not request shutdown: %v", err) log.Fatal(err)
} }
log.Printf("TAPIGetEdge said: %s", r.GetMessage()) log.Info("TAPIGetEdge said: ", r.GetMessage())
} }
// TAPIGetEdgeNode triggers the GetEdgeNode function of the Ciena
// flavoured TAPI client
func TAPIGetEdgeNode(conn *grpc.ClientConn) { func TAPIGetEdgeNode(conn *grpc.ClientConn) {
c := pb.NewGrpcCliClient(conn) c := pb.NewGrpcCliClient(conn)
...@@ -192,11 +174,13 @@ func TAPIGetEdgeNode(conn *grpc.ClientConn) { ...@@ -192,11 +174,13 @@ func TAPIGetEdgeNode(conn *grpc.ClientConn) {
defer cancel() defer cancel()
r, err := c.TAPIGetEdgeNode(ctx, &pb.TAPIRequest{Name: name}) r, err := c.TAPIGetEdgeNode(ctx, &pb.TAPIRequest{Name: name})
if err != nil { if err != nil {
log.Fatalf("could not request shutdown: %v", err) log.Fatal(err)
} }
log.Printf("TAPIGetEdgeNode said: %s", r.GetMessage()) log.Info("TAPIGetEdgeNode said: ", r.GetMessage())
} }
// TAPIGetLink triggers the GetLink function of the Ciena
// flavoured TAPI client
func TAPIGetLink(conn *grpc.ClientConn) { func TAPIGetLink(conn *grpc.ClientConn) {
c := pb.NewGrpcCliClient(conn) c := pb.NewGrpcCliClient(conn)
...@@ -210,7 +194,7 @@ func TAPIGetLink(conn *grpc.ClientConn) { ...@@ -210,7 +194,7 @@ func TAPIGetLink(conn *grpc.ClientConn) {
defer cancel() defer cancel()
r, err := c.TAPIGetLink(ctx, &pb.TAPIRequest{Name: name}) r, err := c.TAPIGetLink(ctx, &pb.TAPIRequest{Name: name})
if err != nil { if err != nil {
log.Fatalf("could not request shutdown: %v", err) log.Fatal(err)
} }
log.Printf("TAPIGetLink said: %s", r.GetMessage()) log.Info("TAPIGetLink said: ", r.GetMessage())
} }
\ No newline at end of file
...@@ -83,7 +83,7 @@ func LoglevelOutput(level Level, out io.Writer) { ...@@ -83,7 +83,7 @@ func LoglevelOutput(level Level, out io.Writer) {
l.lock.Lock() l.lock.Lock()
defer l.lock.Unlock() defer l.lock.Unlock()
l.LoglevelWriter[level] = out l.LoglevelWriter[level] = out
if reflect.TypeOf(out) == reflect.TypeOf(&syslog.Writer{}) { if reflect.TypeOf(out) == reflect.TypeOf(&syslog.Writer{}) {
l.toSyslog[level] = true l.toSyslog[level] = true
} }
} }
...@@ -94,7 +94,7 @@ func Debug(args ...interface{}) { ...@@ -94,7 +94,7 @@ func Debug(args ...interface{}) {
log(DEBUG, args...) log(DEBUG, args...)
} }
//Debug passes the DEBUG flag and a //Info passes the INFO flag and a
//message to the logger //message to the logger
func Info(args ...interface{}) { func Info(args ...interface{}) {
log(INFO, args...) log(INFO, args...)
......
package log package log
// Level is an 8 bit integer representing a
// log level for the logger
type Level uint8 type Level uint8
// Constants for more verbose integer
// values
const ( const (
PANIC Level = iota PANIC Level = iota
FATAL FATAL
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
This file contains the grpc cli server-side calls. This file contains the grpc cli server-side calls.
Functions here should call other functions in charge of the Functions here should call other functions in charge of the
particular task. particular task.
*/ */
package nucleus package nucleus
...@@ -24,7 +23,7 @@ type server struct { ...@@ -24,7 +23,7 @@ type server struct {
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Info("Received: ", in.GetName()) log.Info("Received: ", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName(), GoSDNInfo: "goSDN in version: DEVELOP"}, nil return &pb.HelloReply{Message: "Hello " + in.GetName(), GoSDNInfo: "goSDN in version: DEVELOP"}, nil
} }
func (s *server) Shutdown(ctx context.Context, in *pb.ShutdownRequest) (*pb.ShutdownReply, error) { func (s *server) Shutdown(ctx context.Context, in *pb.ShutdownRequest) (*pb.ShutdownReply, error) {
......
...@@ -22,14 +22,16 @@ type clientConfigs struct { ...@@ -22,14 +22,16 @@ type clientConfigs struct {
Client []interfaces.ClientConfig `toml:"client"` Client []interfaces.ClientConfig `toml:"client"`
} }
// Core is the representation of the controllers core
type Core struct { type Core struct {
//Assert type with clients[key].(*MCPClient) //Assert type with clients[key].(*MCPClient)
clients map[string]interfaces.Client clients map[string]interfaces.Client
database database.Database database database.Database
config controllerConfig config controllerConfig
IsRunning chan bool IsRunning chan bool
} }
//Init does start-up housekeeping like reading controller and client config files
func (c *Core) Init(socket, configFileController, configFileClient string, IsRunningChannel chan bool) { func (c *Core) Init(socket, configFileController, configFileClient string, IsRunningChannel chan bool) {
if err := c.readControllerConfig(configFileController); err != nil { if err := c.readControllerConfig(configFileController); err != nil {
log.Fatal(err) log.Fatal(err)
...@@ -48,13 +50,14 @@ func (c *Core) Init(socket, configFileController, configFileClient string, IsRun ...@@ -48,13 +50,14 @@ func (c *Core) Init(socket, configFileController, configFileClient string, IsRun
} }
} }
// AttachDatabase connects to the database and passes the connectio to the controller core
func (c *Core) AttachDatabase() { func (c *Core) AttachDatabase() {
c.database = database.NewDatabaseClient(c.config.DatabaseSocket, c.config.DatabaseUser, c.config.DatabasePassword, c.config.DatabaseCrypto) c.database = database.NewDatabaseClient(c.config.DatabaseSocket, c.config.DatabaseUser, c.config.DatabasePassword, c.config.DatabaseCrypto)
} }
// Shutdown waits for the shutdown signal and gracefully shuts down once it arrived
func (c *Core) Shutdown() { func (c *Core) Shutdown() {
<-c.IsRunning
<- c.IsRunning
log.Info("Received shutdown signal. Shutting down") log.Info("Received shutdown signal. Shutting down")
f, err := os.Create(c.config.ConfigPath) f, err := os.Create(c.config.ConfigPath)
...@@ -69,7 +72,7 @@ func (c *Core) Shutdown() { ...@@ -69,7 +72,7 @@ func (c *Core) Shutdown() {
os.Exit(0) os.Exit(0)
} }
func (c *Core)readControllerConfig(configFileController string) error { func (c *Core) readControllerConfig(configFileController string) error {
if configFileController == "" { if configFileController == "" {
configFileController = "gosdn.toml" configFileController = "gosdn.toml"
} }
...@@ -88,19 +91,19 @@ func (c *Core)readControllerConfig(configFileController string) error { ...@@ -88,19 +91,19 @@ func (c *Core)readControllerConfig(configFileController string) error {
return nil return nil
} }
func (c *Core)readClientConfig(configFileClient string) error { func (c *Core) readClientConfig(configFileClient string) error {
if configFileClient == "" { if configFileClient == "" {
configFileClient = "clients.toml" configFileClient = "clients.toml"
} }
if _,err := os.Stat(configFileClient); err != nil { if _, err := os.Stat(configFileClient); err != nil {
return err return err
} }
clients := clientConfigs{} clients := clientConfigs{}
if _,err := toml.DecodeFile(configFileClient, &clients); err != nil { if _, err := toml.DecodeFile(configFileClient, &clients); err != nil {
return err return err
} }
for _,client := range clients.Client { for _, client := range clients.Client {
c.clients[client.Identifier] = ciena.NewMCPClient(client.Endpoint, client.Username, client.Password, &c.database, &client) c.clients[client.Identifier] = ciena.NewMCPClient(client.Endpoint, client.Username, client.Password, &c.database, &client)
} }
return nil return nil
} }
\ No newline at end of file
package interfaces package interfaces
// Client provides an interface for
// SBI protocol clients
type Client interface { type Client interface {
GetConfig() ClientConfig GetConfig() ClientConfig
} }
package interfaces package interfaces
// ClientConfig contains SBI client
// configuration parameters
type ClientConfig struct { type ClientConfig struct {
Identifier string `toml:"identifier"` Identifier string `toml:"identifier"`
Endpoint string `toml:"endpoint"` Endpoint string `toml:"endpoint"`
......
...@@ -17,7 +17,7 @@ func StartAndRun(socket, filename string, IsRunningChannel chan bool) { ...@@ -17,7 +17,7 @@ func StartAndRun(socket, filename string, IsRunningChannel chan bool) {
clients: make(map[string]interfaces.Client), clients: make(map[string]interfaces.Client),
database: database.Database{}, database: database.Database{},
} }
core.Init(socket, filename,"", IsRunningChannel) core.Init(socket, filename, "", IsRunningChannel)
// Start the GRCP CLI // Start the GRCP CLI
go getCLIGoing(&core) go getCLIGoing(&core)
go core.Shutdown() go core.Shutdown()
......
...@@ -23,11 +23,13 @@ type MCPClient struct { ...@@ -23,11 +23,13 @@ type MCPClient struct {
config *interfaces.ClientConfig config *interfaces.ClientConfig
} }
// GetConfig returns a ClientConfig struct containing
// the current configuration stat of the Ciena SBI client
func (c MCPClient) GetConfig() interfaces.ClientConfig { func (c MCPClient) GetConfig() interfaces.ClientConfig {
return *c.config return *c.config
} }
//NewMCPClient creates a client //NewMCPClient creates a Ciena flavores TAPI client
func NewMCPClient(endpoint, username, password string, database *database.Database, config *interfaces.ClientConfig) *MCPClient { func NewMCPClient(endpoint, username, password string, database *database.Database, config *interfaces.ClientConfig) *MCPClient {
// create the transport // create the transport
transport := httptransport.New(endpoint, "/", nil) transport := httptransport.New(endpoint, "/", nil)
...@@ -46,10 +48,12 @@ func NewMCPClient(endpoint, username, password string, database *database.Databa ...@@ -46,10 +48,12 @@ func NewMCPClient(endpoint, username, password string, database *database.Databa
client: client, client: client,
database: database, database: database,
buffer: buffer, buffer: buffer,
config: config, config: config,
} }
} }
// GetConnections implements the TAPI Connectivity GetConnections call with a grain of
// Ciena salt. The response is written to the client's buffer and passed to the database
func (c *MCPClient) GetConnections() error { func (c *MCPClient) GetConnections() error {
defer c.buffer.Reset() defer c.buffer.Reset()
_, err := c.client.TapiConnectivityCore.GetTapiCoreContextConnection(nil) _, err := c.client.TapiConnectivityCore.GetTapiCoreContextConnection(nil)
...@@ -58,6 +62,8 @@ func (c *MCPClient) GetConnections() error { ...@@ -58,6 +62,8 @@ func (c *MCPClient) GetConnections() error {
return err return err
} }
// GetLinks implements the TAPI Topology GetLinks call with a grain of
// Ciena salt. The response is written to the client's buffer and passed to the database
func (c *MCPClient) GetLinks() error { func (c *MCPClient) GetLinks() error {
defer c.buffer.Reset() defer c.buffer.Reset()
_, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyLink(nil) _, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyLink(nil)
...@@ -66,6 +72,8 @@ func (c *MCPClient) GetLinks() error { ...@@ -66,6 +72,8 @@ func (c *MCPClient) GetLinks() error {
return err return err
} }
// GetNodes implements the TAPI Topology GetNodes call with a grain of
// Ciena salt. The response is written to the client's buffer and passed to the database
func (c *MCPClient) GetNodes() error { func (c *MCPClient) GetNodes() error {
defer c.buffer.Reset() defer c.buffer.Reset()
_, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNode(nil) _, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNode(nil)
...@@ -74,6 +82,8 @@ func (c *MCPClient) GetNodes() error { ...@@ -74,6 +82,8 @@ func (c *MCPClient) GetNodes() error {
return err return err
} }
// GetNodeEdgePoints implements the TAPI Topology GetNodeEdgePoints call with a grain of
// Ciena salt. The response is written to the client's buffer and passed to the database
func (c *MCPClient) GetNodeEdgePoints() error { func (c *MCPClient) GetNodeEdgePoints() error {
defer c.buffer.Reset() defer c.buffer.Reset()
_, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNodeEdgePoint(nil) _, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNodeEdgePoint(nil)
......
...@@ -5,10 +5,13 @@ import ( ...@@ -5,10 +5,13 @@ import (
"io" "io"
) )
// YANGConsumer is a auxillary type to redirect the response
// of an RESTCONF call to a ygot YANG unmarshaler
type YANGConsumer struct { type YANGConsumer struct {
Data *bytes.Buffer Data *bytes.Buffer
} }
// Consume reads the received data into a byte buffer
func (yc YANGConsumer) Consume(reader io.Reader, _ interface{}) error { func (yc YANGConsumer) Consume(reader io.Reader, _ interface{}) error {
_, err := yc.Data.ReadFrom(reader) _, err := yc.Data.ReadFrom(reader)
return err return err
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment