Skip to content
Snippets Groups Projects
Commit 5304922e authored by Martin Stiemerling's avatar Martin Stiemerling
Browse files

hopefully fixed merge conflict

parents 54f78cb0 d83c2f9f
Branches
Tags
1 merge request!18Develop
This commit is part of merge request !18. Comments created here will be created in the context of that merge request.
package database
import (
"log"
"github.com/neo4j/neo4j-go-driver/neo4j"
)
//Database
type Database struct {
driver neo4j.Driver
session neo4j.Session
}
//NewDatabaseClient creates a database client
func NewDatabaseClient(uri, username, password string, encrypted bool) Database {
//TODO: defer close()?
// probably pretty nasty since it creates copies
driver := createDriver(uri, username, password, encrypted)
session := createSession(driver)
return Database{
driver: driver,
session: session,
}
}
//createDriver creates a neo4j.Driver instance
func createDriver(uri, username, password string, encrypted bool) neo4j.Driver {
driver, err := neo4j.NewDriver(
uri,
neo4j.BasicAuth(username, password, ""),
func(c *neo4j.Config) {
c.Encrypted = encrypted
},
)
logError("failed creating database Driver", err)
return driver
}
//createSession creates a neo4j.Session
func createSession(driver neo4j.Driver) neo4j.Session {
sessionConfig := neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite}
session, err := driver.NewSession(sessionConfig)
logError("failed creating database session", err)
return session
}
//StoreNodes stores the given nodes to the database
func (d Database) StoreNodes(json string) {
session := d.session
query :=
`
WITH apoc.convert.fromJsonMap($stringToAdd)
AS value
UNWIND value.data as d
MERGE (device:Device {id: d.object_id})
ON CREATE SET device.nativeName = d.object_data.name[0].value,
device.deviceType = d.object_data.name[1].value,
device.serialNumber = d.object_data.name[2].value,
device.softwareVersion = d.object_data.name[3].value,
device.` + "`operational-state` = d.object_data.`operational-state`"
_, err := session.Run(
query, map[string]interface{}{
"stringToAdd": json,
})
logError("failed storing Nodes into database", err)
log.Printf("successfully added Nodes into database")
}
//StoreNodeEdgePoints stores the given node edge points (interfaces)
func (d Database) StoreNodeEdgePoints(json string) {
session := d.session
queryEdgePoints :=
`
WITH apoc.convert.fromJsonMap($stringToAdd)
AS value
UNWIND value.data as i
MERGE (interface:Interface {id: i.object_id})
ON CREATE SET interface.object_type =i.object_type,
interface.localId = i.object_data.name[0].value,
interface.location = i.object_data.name[1].value,
interface.` + "`containing-node` = i.object_data.`containing-node`"
_, err := session.Run(
queryEdgePoints, map[string]interface{}{
"stringToAdd": json,
})
logError("failed storing NodeEdgePoints into database", err)
setNodeNodeEdgePointsRelation(session)
log.Printf("successfully added NodeEdgePoints into database")
}
func (d Database) StoreConnections(json string){}
//setNodeNodeEdgePointsRelation creates the database relations between "nodes" and "node edge points"
func setNodeNodeEdgePointsRelation(session neo4j.Session) {
query :=
`
MATCH (d:Device), (i:Interface)
WHERE d.id = i.` + "`containing-node`" + `
CREATE (i)-[:BELONGS_TO]->(d)
`
_, err := session.Run(
query, map[string]interface{}{})
logError("failed storing NodeNodeEdgePointsRelation into database", err)
log.Printf("successfully stored NodeNodeEdgePointsRelation into database")
}
//logError logs error with custom and error message
func logError(message string, err error) {
if err != nil {
log.Fatalf("%v: %v", message, err)
}
}
...@@ -4,20 +4,19 @@ go 1.14 ...@@ -4,20 +4,19 @@ go 1.14
require ( require (
code.fbi.h-da.de/cocsn/swagger/apis v0.0.0-20200924152423-61030cab7b88 code.fbi.h-da.de/cocsn/swagger/apis v0.0.0-20200924152423-61030cab7b88
code.fbi.h-da.de/cocsn/swagger/apis/ciena v0.0.0-20200922140607-29b1f99d0f68 // indirect github.com/BurntSushi/toml v0.3.1
code.fbi.h-da.de/cocsn/yang-modules/generated/ciena v0.0.0-20200922150332-3e03fcde3e37
code.fbi.h-da.de/cocsn/yang-modules/generated/tapi v0.0.0-20200922150332-3e03fcde3e37
github.com/go-openapi/runtime v0.19.22 github.com/go-openapi/runtime v0.19.22
github.com/go-openapi/strfmt v0.19.5 github.com/go-openapi/strfmt v0.19.5
github.com/go-openapi/swag v0.19.9 // indirect
github.com/go-openapi/validate v0.19.11 // indirect
github.com/golang/protobuf v1.4.2 github.com/golang/protobuf v1.4.2
github.com/jessevdk/go-flags v1.4.0 // indirect github.com/google/go-cmp v0.4.1 // indirect
github.com/mattn/go-sqlite3 v1.14.3 github.com/mattn/go-sqlite3 v1.14.3
github.com/openconfig/goyang v0.0.0-20200917201611-633eccb6fa97 // indirect github.com/openconfig/goyang v0.0.0-20200917201611-633eccb6fa97 // indirect
github.com/openconfig/ygot v0.8.7 github.com/openconfig/ygot v0.8.7
github.com/rivo/tview v0.0.0-20200915114512-42866ecf6ca6 github.com/rivo/tview v0.0.0-20200915114512-42866ecf6ca6
github.com/neo4j/neo4j-go-driver v1.8.3
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 // indirect
google.golang.org/genproto v0.0.0-20200519141106-08726f379972 // indirect
google.golang.org/grpc v1.29.1 google.golang.org/grpc v1.29.1
google.golang.org/protobuf v1.23.0 google.golang.org/protobuf v1.23.0
) )
This diff is collapsed.
#example gosdn.toml
CliSocket="localhost:55055"
DatabaseSocket="localhost:7687"
ConfigPath="./gosdn.toml"
\ No newline at end of file
...@@ -5,29 +5,18 @@ import ( ...@@ -5,29 +5,18 @@ import (
"flag" "flag"
) )
// Generate the code out of the yang modules
//go:generate go run $GOPATH/src/github.com/openconfig/ygot/generator/generator.go -path=yang -output_file=yang-processor/gosdnyang.go.go -package_name=gosdnyang -generate_fakeroot -fakeroot_name=device -compress_paths=true -shorten_enum_leaf_names -exclude_modules=ietf-interfaces yang/openconfig-interfaces.yang yang/openconfig-if-ip.yang
type goSDNConfiguration struct {
cliServerAddr4 *string
cliServerPort4 *int
}
func main() { func main() {
// register our supported flags // register our supported flags
cliServerAddr4 := flag.String("cliServerAddr", "127.0.0.1", "The IPv4 Address of the grpcCLI.") cliListenAddr := flag.String("cli-listen-addr", "localhost", "The IP address of the grpcCLI.")
cliServerPort4 := flag.Int("cliServerPort", 55055, "The port number of the grpcCLI") cliListenPort := flag.String("cli-server-port", "55055", "The port number of the grpcCLI")
configFileName := flag.String("config-file", "", "Path to the config file")
flag.Parse() flag.Parse()
cliSocket := *cliListenAddr + *cliListenPort
var myConfiguration = new(goSDNConfiguration)
myConfiguration.cliServerAddr4 = cliServerAddr4
myConfiguration.cliServerPort4 = cliServerPort4
// hand off to cmd for further processing // hand off to cmd for further processing
nucleus.StartUp() nucleus.StartUp(cliSocket, *configFileName)
nucleus.Run() nucleus.Run()
// nothing to see here, please move on! // nothing to see here, please move on!
......
package nucleus package nucleus
import ( import (
yangPro "code.fbi.h-da.de/cocsn/yang-modules/generated/tapi" "code.fbi.h-da.de/cocsn/gosdn/database"
"fmt" "code.fbi.h-da.de/cocsn/gosdn/nucleus/interfaces"
"github.com/openconfig/ygot/ygot" "github.com/BurntSushi/toml"
"net" "log"
"os"
) )
// This is a test function in order to see how to generate JSON encoded openconfig stuff /*
#example gosdn.toml
CliSocket="localhost:55055"
DatabaseSocket="localhost:7687"
ConfigPath="./gosdn.toml"
*/
func AssembleJSON() { type controllerConfig struct {
// Build my device CliSocket string
d := &yangPro.Device{} DatabaseSocket string
DatabaseUser string
DatabasePassword string
DatabaseCrypto bool
ConfigPath string
}
interfaces, _ := net.Interfaces() type Core struct {
for _, iface := range interfaces { clients []interfaces.Client
fmt.Println(iface.Name) database database.Database
} config controllerConfig
}
// EmitJSON from the ygot library directly does .Validate() and outputs JSON in func (c Core) Init(socket, configfile string) {
// the specified format. if configfile == "" {
json, err := ygot.EmitJSON(d, &ygot.EmitJSONConfig{ configfile = "gosdn.toml"
Format: ygot.RFC7951, }
Indent: " ", _, err := os.Stat(configfile)
RFC7951Config: &ygot.RFC7951JSONConfig{
AppendModuleName: true,
},
})
if err != nil { if err != nil {
panic(fmt.Sprintf("JSON demo error: %v", err)) log.Fatal("Config file is missing: ", configfile)
} }
fmt.Println(json)
// and now try to read the data from it... c.config = controllerConfig{}
// Device struct to unmarshal into. if _, err := toml.DecodeFile(configfile, &c.config); err != nil {
loadd := &yangPro.Device{} log.Fatal(err)
if err := yangPro.Unmarshal([]byte(json), loadd); err != nil { }
panic(fmt.Sprintf("Cannot unmarshal JSON: %v", err)) if socket != "localhost:55055" {
c.config.CliSocket = socket
}
if c.config.ConfigPath == "" {
c.config.ConfigPath = configfile
} }
c.database = database.NewDatabaseClient(c.config.DatabaseSocket, c.config.DatabaseUser, c.config.DatabasePassword, c.config.DatabaseCrypto)
}
func (c Core) Shutdown() {
f, err := os.Create(c.config.ConfigPath)
if err != nil {
log.Fatal(err)
}
enc := toml.NewEncoder(f)
if err := enc.Encode(c.config); err != nil {
log.Fatal(err)
}
} }
package restconf package interfaces
type Client interface { type Client interface {
GetConfig() string GetConfig() string
......
package interfaces
type Database interface {
DropTables()
}
type MockDatabase struct {
}
func (db MockDatabase) DropTables() {
}
func NewMockDatabaseClient(uri, username, password string, encrypted bool) Database {
return MockDatabase{}
}
...@@ -10,14 +10,10 @@ import ( ...@@ -10,14 +10,10 @@ import (
"time" "time"
) )
// TODO XXX This has to be moved to some configuration file
const (
cli_control_port = "localhost:55055"
)
// server is used to implement helloworld.GreeterServer. // server is used to implement helloworld.GreeterServer.
type server struct { type server struct {
pb.UnimplementedGreeterServer pb.UnimplementedGreeterServer
core *Core
} }
// SayHello implements helloworld.GreeterServer // SayHello implements helloworld.GreeterServer
...@@ -32,18 +28,17 @@ func (s *server) Shutdown(ctx context.Context, in *pb.ShutdownRequest) (*pb.Shut ...@@ -32,18 +28,17 @@ func (s *server) Shutdown(ctx context.Context, in *pb.ShutdownRequest) (*pb.Shut
return &pb.ShutdownReply{Message: "Shutdown " + in.GetName()}, nil return &pb.ShutdownReply{Message: "Shutdown " + in.GetName()}, nil
} }
func getCLIGoing(core *Core) {
func getCLIGoing() {
log.Println("Starting: GetCLIGoing") log.Println("Starting: GetCLIGoing")
// Boot-up the control interface for the cli // Boot-up the control interface for the cli
cliControlListener, err := net.Listen("tcp", cli_control_port) cliControlListener, err := net.Listen("tcp", core.config.CliSocket)
if err != nil { if err != nil {
log.Fatalf("failed to listen: %v", err) log.Fatalf("failed to listen: %v", err)
} }
cliControlServer := grpc.NewServer() cliControlServer := grpc.NewServer()
pb.RegisterGreeterServer(cliControlServer, &server{}) pb.RegisterGreeterServer(cliControlServer, &server{core: core})
if err := cliControlServer.Serve(cliControlListener); err != nil { if err := cliControlServer.Serve(cliControlListener); err != nil {
log.Fatalf("failed to serve: %v", err) log.Fatalf("failed to serve: %v", err)
} }
...@@ -56,12 +51,14 @@ func getCLIGoing() { ...@@ -56,12 +51,14 @@ func getCLIGoing() {
// Next-up: backend database. // Next-up: backend database.
func StartUp() { func StartUp(socket, filename string) {
log.Println("This is the network superintendent...") log.Println("This is the network superintendent...")
log.Println("Starting my ducks") log.Println("Starting my ducks")
// Init the Core
core := Core{}
core.Init(socket, filename)
// Start the GRCP CLI // Start the GRCP CLI
go getCLIGoing() go getCLIGoing(&core)
log.Println("and ready for take off") log.Println("and ready for take off")
} }
...@@ -76,7 +73,7 @@ func Run() { ...@@ -76,7 +73,7 @@ func Run() {
for isRunning { for isRunning {
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)
log.Println(("Still alive...")) log.Println("Still alive...")
} }
log.Println("Good bye....!") log.Println("Good bye....!")
......
package ciena package ciena
import ( import (
"code.fbi.h-da.de/cocsn/gosdn/database"
"code.fbi.h-da.de/cocsn/gosdn/restconf/util" "code.fbi.h-da.de/cocsn/gosdn/restconf/util"
apiclient "code.fbi.h-da.de/cocsn/swagger/apis/mcp/client" apiclient "code.fbi.h-da.de/cocsn/swagger/apis/mcp/client"
"crypto/tls" "crypto/tls"
...@@ -14,6 +15,7 @@ import ( ...@@ -14,6 +15,7 @@ import (
type MCPClient struct { type MCPClient struct {
transport *httptransport.Runtime transport *httptransport.Runtime
client *apiclient.ServiceTopologyTAPI client *apiclient.ServiceTopologyTAPI
database *database.Database
buf *[]byte buf *[]byte
} }
...@@ -23,7 +25,7 @@ func (c MCPClient) GetConfig() string { ...@@ -23,7 +25,7 @@ func (c MCPClient) GetConfig() string {
} }
//NewMCPClient creates a client //NewMCPClient creates a client
func NewMCPClient(endpoint, username, password string) MCPClient { func NewMCPClient(endpoint, username, password string, database *database.Database) MCPClient {
// create the transport // create the transport
transport := httptransport.New(endpoint, "/", nil) transport := httptransport.New(endpoint, "/", nil)
transport.Transport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} transport.Transport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
...@@ -40,30 +42,31 @@ func NewMCPClient(endpoint, username, password string) MCPClient { ...@@ -40,30 +42,31 @@ func NewMCPClient(endpoint, username, password string) MCPClient {
return MCPClient{ return MCPClient{
transport: transport, transport: transport,
client: client, client: client,
database: database,
buf: &buf, buf: &buf,
} }
} }
func (c MCPClient) GetConnections() (error, []byte) { func (c MCPClient) GetConnections() error {
c.buf = nil c.buf = nil
_, err := c.client.TapiConnectivityCore.GetTapiCoreContextConnection(nil) _, err := c.client.TapiConnectivityCore.GetTapiCoreContextConnection(nil)
responseBuffer := *c.buf c.database.StoreConnections(string(*c.buf))
c.buf = nil c.buf = nil
return err, responseBuffer return err
} }
func (c MCPClient) GetNodes() (error, []byte) { func (c MCPClient) GetNodes() error {
c.buf = nil c.buf = nil
_, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNode(nil) _, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNode(nil)
responseBuffer := *c.buf c.database.StoreNodes(string(*c.buf))
c.buf = nil c.buf = nil
return err, responseBuffer return err
} }
func (c MCPClient) GetNodeEdgePoints() (error, []byte) { func (c MCPClient) GetNodeEdgePoints() error {
c.buf = nil c.buf = nil
_, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNodeEdgePoint(nil) _, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNodeEdgePoint(nil)
responseBuffer := *c.buf c.database.StoreNodeEdgePoints(string(*c.buf))
c.buf = nil c.buf = nil
return err, responseBuffer return err
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment