diff --git a/go.mod b/go.mod index dd79e0b9f60580331c8fb96e184c765d554ff432..ac3f07b9f4e1ca401334134ae4e9d97bf1bab8a5 100644 --- a/go.mod +++ b/go.mod @@ -10,12 +10,13 @@ require ( github.com/go-openapi/runtime v0.19.22 github.com/go-openapi/strfmt v0.19.5 github.com/golang/protobuf v1.4.2 + github.com/google/uuid v1.1.2 github.com/neo4j/neo4j-go-driver v1.8.3 github.com/onsi/ginkgo v1.13.0 // indirect github.com/openconfig/ygot v0.8.7 github.com/rivo/tview v0.0.0-20201018122409-d551c850a743 - github.com/tidwall/gjson v1.6.3 github.com/sirupsen/logrus v1.4.2 + github.com/tidwall/gjson v1.6.3 golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect google.golang.org/grpc v1.29.1 google.golang.org/protobuf v1.23.0 diff --git a/go.sum b/go.sum index 6b90cf7a5ba559555977fa50e1c30c224c7bb174..d394443518aa39b20e7088849009fb8f52055396 100644 --- a/go.sum +++ b/go.sum @@ -162,6 +162,8 @@ github.com/google/protobuf v3.11.4+incompatible/go.mod h1:lUQ9D1ePzbH2PrIS7ob/bj github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= @@ -172,6 +174,7 @@ github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0Lh github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= diff --git a/gosdn.puml b/gosdn.puml new file mode 100644 index 0000000000000000000000000000000000000000..1dc2379006cdef8990adf2f73dc4fe5ddd414c51 --- /dev/null +++ b/gosdn.puml @@ -0,0 +1,118 @@ +@startuml +namespace nucleus { + class ClientConfig << (S,Aquamarine) >> { + + Identifier string + + Endpoint string + + Username string + + Password string + + GjsonDefaultPath string + + GjsonConnectionsPath string + + } + class Core << (S,Aquamarine) >> { + - devices <font color=blue>map</font>[string]Device + - southboundInterfaces <font color=blue>map</font>[string]interfaces.SouthboundInterface + - prinipalNetworkDomains <font color=blue>map</font>[uuid.UUID]interfaces.PrincipalNetworkDomain + - database database.Database + - config controllerConfig + + + IsRunning <font color=blue>chan</font> bool + + - readControllerConfig(configFileController string) error + + + Init(socket string, configFileController string, configFileClient string, IsRunningChannel <font color=blue>chan</font> bool) + + AttachDatabase() + + Shutdown() + + } + class Device << (S,Aquamarine) >> { + - device ygot.GoStruct + + + SBI interfaces.SouthboundInterface + + Config DeviceConfig + + } + class DeviceConfig << (S,Aquamarine) >> { + + Identifier uuid.UUID + + Endpoint string + + Username string + + Password string + + } + interface PrincipalNetworkDomain { + + Destroy() error + + AddSbi() error + + RemoveSbi() error + + AddDevice( interfaces.Device) error + + RemoveDevice(uuid uuid.UUID) error + + } + interface SouthboundInterface { + } + class buf << (S,Aquamarine) >> { + + Write(p []byte) (int, error) + + } + class controllerConfig << (S,Aquamarine) >> { + + CliSocket string + + DatabaseSocket string + + DatabaseUser string + + DatabasePassword string + + DatabaseCrypto bool + + ConfigPath string + + } + class logConnection << (S,Aquamarine) >> { + - stream proto.GrpcCli_CreateLogStreamServer + - id string + - active bool + - error <font color=blue>chan</font> error + + } + class nucleus.buf << (T, #FF7700) >> { + } + class pndImplementation << (S,Aquamarine) >> { + - name string + - sbiContainer <font color=blue>map</font>[string]*interfaces.SouthboundInterface + - devices <font color=blue>map</font>[uuid.UUID]Device + + + Destroy() error + + AddSbi() error + + RemoveSbi() error + + AddDevice(device Device) error + + RemoveDevice(uuid uuid.UUID) error + + } + class server << (S,Aquamarine) >> { + - core *Core + - logConnections []*logConnection + + + SayHello(ctx context.Context, in *proto.HelloRequest) (*proto.HelloReply, error) + + CreateLogStream(req *emptypb.Empty, stream proto.GrpcCli_CreateLogStreamServer) error + + BroadcastLog(log *proto.LogReply) + + Shutdown(ctx context.Context, in *proto.ShutdownRequest) (*proto.ShutdownReply, error) + + TAPIGetEdge(ctx context.Context, in *proto.TAPIRequest) (*proto.TAPIReply, error) + + TAPIGetEdgeNode(ctx context.Context, in *proto.TAPIRequest) (*proto.TAPIReply, error) + + TAPIGetLink(ctx context.Context, in *proto.TAPIRequest) (*proto.TAPIReply, error) + + } +} +"proto.UnimplementedGrpcCliServer" *-- "nucleus.server" + + +namespace sbi { + class OpenConfig << (S,Aquamarine) >> { + - name string + - clientContainer []Client + + + AddClient() error + + RemoveClient() error + + CollectHeartbeats() error + + ListClients() <font color=blue>map</font>[int]interfaces.Client + + } +} + + +"__builtin__.[]byte" #.. "nucleus.buf" +@enduml diff --git a/nucleus/cli-handling.go b/nucleus/cli-handling.go index 81c11d1a8e03c68d9071f2b2df2d202397002403..5bc95e055a7bb405ca827388fa79d4ff347185ed 100644 --- a/nucleus/cli-handling.go +++ b/nucleus/cli-handling.go @@ -135,7 +135,7 @@ func getCLIGoing(core *Core) { // SBI specific calls, by now TAPI only func (s *server) TAPIGetEdge(ctx context.Context, in *pb.TAPIRequest) (*pb.TAPIReply, error) { log.Info("Received: ", in.GetName()) - if err := s.core.clients["ciena-mcp"].(*ciena.MCPClient).GetNodes(); err != nil { + if err := s.core.devices["ciena-mcp"].(*ciena.MCPClient).GetNodes(); err != nil { log.Error(err) return &pb.TAPIReply{Message: "TAPI error"}, nil } @@ -144,7 +144,7 @@ func (s *server) TAPIGetEdge(ctx context.Context, in *pb.TAPIRequest) (*pb.TAPIR func (s *server) TAPIGetEdgeNode(ctx context.Context, in *pb.TAPIRequest) (*pb.TAPIReply, error) { log.Info("Received: ", in.GetName()) - if err := s.core.clients["ciena-mcp"].(*ciena.MCPClient).GetNodeEdgePoints(); err != nil { + if err := s.core.devices["ciena-mcp"].(*ciena.MCPClient).GetNodeEdgePoints(); err != nil { log.Error(err) return &pb.TAPIReply{Message: "TAPI error"}, nil } @@ -153,7 +153,7 @@ func (s *server) TAPIGetEdgeNode(ctx context.Context, in *pb.TAPIRequest) (*pb.T func (s *server) TAPIGetLink(ctx context.Context, in *pb.TAPIRequest) (*pb.TAPIReply, error) { log.Info("Received: ", in.GetName()) - if err := s.core.clients["ciena-mcp"].(*ciena.MCPClient).GetLinks(); err != nil { + if err := s.core.devices["ciena-mcp"].(*ciena.MCPClient).GetLinks(); err != nil { log.Error(err) return &pb.TAPIReply{Message: "TAPI error"}, nil } diff --git a/nucleus/controller.go b/nucleus/controller.go index 7d0541f881fb8ffd86e653c220bfcef4806eb5c6..444c5d4c437bc7769c634eeb9fa84a29e6c1aac0 100644 --- a/nucleus/controller.go +++ b/nucleus/controller.go @@ -2,9 +2,9 @@ package nucleus import ( "code.fbi.h-da.de/cocsn/gosdn/database" - "code.fbi.h-da.de/cocsn/gosdn/nucleus/interfaces" - "code.fbi.h-da.de/cocsn/gosdn/sbi/restconf/client/ciena" + nucleus "code.fbi.h-da.de/cocsn/gosdn/nucleus/interfaces" "github.com/BurntSushi/toml" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "os" ) @@ -18,17 +18,14 @@ type controllerConfig struct { ConfigPath string } -type clientConfigs struct { - Client []interfaces.ClientConfig `toml:"client"` -} - // Core is the representation of the controllers core type Core struct { - //Assert type with clients[key].(*MCPClient) - clients map[string]interfaces.Client - database database.Database - config controllerConfig - IsRunning chan bool + devices map[string]Device + southboundInterfaces map[string]nucleus.SouthboundInterface + prinipalNetworkDomains map[uuid.UUID]nucleus.PrincipalNetworkDomain + database database.Database + config controllerConfig + IsRunning chan bool } //Init does start-up housekeeping like reading controller and client config files @@ -44,10 +41,6 @@ func (c *Core) Init(socket, configFileController, configFileClient string, IsRun c.AttachDatabase() c.IsRunning = IsRunningChannel - - if err := c.readClientConfig(configFileClient); err != nil { - log.Fatal(err) - } } // AttachDatabase connects to the database and passes the connectio to the controller core @@ -90,20 +83,3 @@ func (c *Core) readControllerConfig(configFileController string) error { } return nil } - -func (c *Core) readClientConfig(configFileClient string) error { - if configFileClient == "" { - configFileClient = "configs/clients.toml" - } - if _, err := os.Stat(configFileClient); err != nil { - return err - } - clients := clientConfigs{} - if _, err := toml.DecodeFile(configFileClient, &clients); err != nil { - return err - } - for _, client := range clients.Client { - c.clients[client.Identifier] = ciena.NewMCPClient(client.Endpoint, client.Username, client.Password, &c.database, &client) - } - return nil -} diff --git a/nucleus/device.go b/nucleus/device.go new file mode 100644 index 0000000000000000000000000000000000000000..be672a18f8e63ee0579265cc3f1634802e651ff9 --- /dev/null +++ b/nucleus/device.go @@ -0,0 +1,20 @@ +package nucleus + +import ( + nucleus "code.fbi.h-da.de/cocsn/gosdn/nucleus/interfaces" + "github.com/google/uuid" + "github.com/openconfig/ygot/ygot" +) + +type Device struct { + device ygot.GoStruct + SBI nucleus.SouthboundInterface + Config DeviceConfig +} + +type DeviceConfig struct { + Identifier uuid.UUID + Endpoint string + Username string + Password string +} diff --git a/nucleus/interfaces/clientConfig.go b/nucleus/interfaces/clientConfig.go index b90df804102925a958eea25977486e275ebd48c3..d29a14c3cc29aa1f83646f53d295feecbe0fb7ce 100644 --- a/nucleus/interfaces/clientConfig.go +++ b/nucleus/interfaces/clientConfig.go @@ -1,4 +1,4 @@ -package interfaces +package nucleus // ClientConfig contains SBI client // configuration parameters diff --git a/nucleus/interfaces/interfaces.go b/nucleus/interfaces/interfaces.go index b1fab9242901d819e04198b2ebe2f355ad5ab326..a36ec03abbcf9b4a02d94c318208cad9a7e54666 100644 --- a/nucleus/interfaces/interfaces.go +++ b/nucleus/interfaces/interfaces.go @@ -1,17 +1,9 @@ -package interfaces +package nucleus -// Port provides an interface for -// the device's ports -type Port interface { -} - -// Client provides an interface for -// SBI client implementations -type Client interface { - GetConfig() ClientConfig - ListPorts() map[int]Port - PushReceiver() error -} +import ( + "code.fbi.h-da.de/cocsn/gosdn/nucleus" + "github.com/google/uuid" +) // PrincipalNetworkDomain provides an // interface for PND implementations @@ -19,13 +11,11 @@ type PrincipalNetworkDomain interface { Destroy() error AddSbi() error RemoveSbi() error + AddDevice(nucleus.Device) error + RemoveDevice(uuid uuid.UUID) error } // SouthboundInterface provides an // interface for SBI implementations type SouthboundInterface interface { - AddClient() error - RemoveClient() error - CollectHeartbeats() error - ListClients() map[int]Client } diff --git a/nucleus/nucleus-core.go b/nucleus/nucleus-core.go index 4e92cf46abe187399459dfb8aa5428ee450d0af0..e19626280c1bfef07fa2216ee05f8ec08f6edd99 100644 --- a/nucleus/nucleus-core.go +++ b/nucleus/nucleus-core.go @@ -14,7 +14,7 @@ func StartAndRun(socket, filename string, IsRunningChannel chan bool) { // Init the Core core := Core{ - clients: make(map[string]interfaces.Client), + devices: make(map[string]nucleus.Client), database: database.Database{}, } core.Init(socket, filename, "", IsRunningChannel) diff --git a/nucleus/principalNetworkDomain.go b/nucleus/principalNetworkDomain.go index f77f544dca7f7fe9813cbc53e88ecdb105a88179..2eb43ec705fa49228b6dcea643945c2eba7096d5 100644 --- a/nucleus/principalNetworkDomain.go +++ b/nucleus/principalNetworkDomain.go @@ -1,17 +1,23 @@ package nucleus -import "code.fbi.h-da.de/cocsn/gosdn/nucleus/interfaces" +import ( + "code.fbi.h-da.de/cocsn/gosdn/nucleus/interfaces" + "github.com/google/uuid" +) type pndImplementation struct { name string - sbiContainer []interfaces.SouthboundInterface + sbiContainer map[string]*nucleus.SouthboundInterface + devices map[uuid.UUID]Device } -//NewPNDImplementation creates a Principle Network Domain -func NewPNDImplementation(name string, sbi ...interfaces.SouthboundInterface) interfaces.PrincipalNetworkDomain { +//NewPND creates a Principle Network Domain +func NewPND(name string, sbi *nucleus.SouthboundInterface) nucleus.PrincipalNetworkDomain { + sbic := make(map[string]*nucleus.SouthboundInterface) + sbic["default"] = sbi return &pndImplementation{ name: name, - sbiContainer: sbi, + sbiContainer: sbic, } } @@ -28,6 +34,14 @@ func (pnd *pndImplementation) RemoveSbi() error { return removeSbi() } +func (pnd *pndImplementation) AddDevice(device Device) error { + return addDevice(device) +} + +func (pnd *pndImplementation) RemoveDevice(uuid uuid.UUID) error { + return removeDevice(uuid) +} + // Actual implementation, bind to struct if // neccessary func destroy() error { @@ -41,3 +55,11 @@ func addSbi() error { func removeSbi() error { return nil } + +func addDevice(device Device) error { + return nil +} + +func removeDevice(uuid uuid.UUID) error { + return nil +} diff --git a/sbi/restconf/southboundInterface.go b/nucleus/sbi/openConfig.go similarity index 51% rename from sbi/restconf/southboundInterface.go rename to nucleus/sbi/openConfig.go index 1eae1e67bebe9b29aa969b4cf6fb7ae2b42de1a6..4c46aa4d1eca70d3b8592134b52e986c3368865a 100644 --- a/sbi/restconf/southboundInterface.go +++ b/nucleus/sbi/openConfig.go @@ -1,34 +1,34 @@ -package restconf +package sbi import "code.fbi.h-da.de/cocsn/gosdn/nucleus/interfaces" -type southboundInterface struct { +type OpenConfig struct { name string - clientContainer []interfaces.Client + clientContainer []Client } //NewSouthboundInterface creates a Southbound Interface -func NewSouthboundInterface(name string, clients ...interfaces.Client) interfaces.SouthboundInterface { - return &southboundInterface{ +func NewSouthboundInterface(name string, clients ...nucleus.Client) nucleus.SouthboundInterface { + return &OpenConfig{ name: name, clientContainer: clients, } } // Interface satisfaction -func (sbi *southboundInterface) AddClient() error { +func (sbi *OpenConfig) AddClient() error { return addClient() } -func (sbi *southboundInterface) RemoveClient() error { +func (sbi *OpenConfig) RemoveClient() error { return removeClient() } -func (sbi *southboundInterface) CollectHeartbeats() error { +func (sbi *OpenConfig) CollectHeartbeats() error { return collectHeartbeats() } -func (sbi *southboundInterface) ListClients() map[int]interfaces.Client { +func (sbi *OpenConfig) ListClients() map[int]nucleus.Client { return listClients() } @@ -46,6 +46,6 @@ func collectHeartbeats() error { return nil } -func listClients() map[int]interfaces.Client { +func listClients() map[int]nucleus.Client { return nil } diff --git a/nucleus/transport/gnmi.go b/nucleus/transport/gnmi.go new file mode 100644 index 0000000000000000000000000000000000000000..d11d0be550c23abc18c55baede0a85a893b8edca --- /dev/null +++ b/nucleus/transport/gnmi.go @@ -0,0 +1 @@ +package transport diff --git a/nucleus/transport/restconf.go b/nucleus/transport/restconf.go new file mode 100644 index 0000000000000000000000000000000000000000..d11d0be550c23abc18c55baede0a85a893b8edca --- /dev/null +++ b/nucleus/transport/restconf.go @@ -0,0 +1 @@ +package transport diff --git a/sbi/restconf/client/ciena/client.go b/sbi/restconf/client/ciena/client.go index 853afbf12ff5d628f726300daff2738607d1163f..114d5d2055dfb6689501546856ceb17b1c51f355 100644 --- a/sbi/restconf/client/ciena/client.go +++ b/sbi/restconf/client/ciena/client.go @@ -13,8 +13,8 @@ import ( httptransport "github.com/go-openapi/runtime/client" "github.com/go-openapi/strfmt" "github.com/openconfig/ygot/ygot" - "github.com/tidwall/gjson" log "github.com/sirupsen/logrus" + "github.com/tidwall/gjson" "net/http" "strings" ) @@ -25,19 +25,19 @@ type MCPClient struct { client *apiclient.ServiceTopologyTAPI database *database.Database buffer *bytes.Buffer - config *interfaces.ClientConfig + config *nucleus.ClientConfig device ygot.GoStruct } // 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() nucleus.ClientConfig { return *c.config } // ListPorts is a stub to satisfy the interface // TODO: Implement -func (c MCPClient) ListPorts() map[int]interfaces.Port { +func (c MCPClient) ListPorts() map[int]nucleus.Port { return nil } @@ -48,7 +48,7 @@ func (c MCPClient) PushReceiver() error { } //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 *nucleus.ClientConfig) *MCPClient { // create the transport transport := httptransport.New(endpoint, "/", nil) transport.Transport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} diff --git a/nucleus/sbi-general.go b/sbi/sbi-general.go similarity index 94% rename from nucleus/sbi-general.go rename to sbi/sbi-general.go index 0795a665354292cd1a09e2051b84658f3607d72e..9e7247dcf1592df91d1ea4e61da2e7515e854405 100644 --- a/nucleus/sbi-general.go +++ b/sbi/sbi-general.go @@ -1,4 +1,4 @@ -package nucleus +package sbi import ( "fmt" @@ -10,7 +10,7 @@ type SBIGreeter interface { SBIHello() } -func SBILoader () { +func SBILoader() { modPath := "/Users/mls/go/src/code.fbi.h-da.de/cocsn/byowsbi/byowsbi.o" // open the so file that contains the SBI-plugin as step before loading the symbols @@ -38,4 +38,3 @@ func SBILoader () { // use me! sbigreeter.SBIHello() } -