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

Embedded ygot.GoStruct in nucleus.Device

Also moved transport config entirely to transport. nucleus.DeviceConfig might be obsolete
parent a734cd6f
Branches
Tags
4 merge requests!100Resolve "Remove all exported API calls from device",!98Resolve "gNMI proto encoding",!91"Overhaul Architecture",!90Develop
...@@ -3,8 +3,6 @@ package main ...@@ -3,8 +3,6 @@ package main
import ( import (
"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi" "code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
"code.fbi.h-da.de/cocsn/gosdn/nucleus" "code.fbi.h-da.de/cocsn/gosdn/nucleus"
schema "code.fbi.h-da.de/cocsn/yang-models/generated/arista"
"context"
"github.com/google/uuid" "github.com/google/uuid"
gpb "github.com/openconfig/gnmi/proto/gnmi" gpb "github.com/openconfig/gnmi/proto/gnmi"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
...@@ -12,50 +10,47 @@ import ( ...@@ -12,50 +10,47 @@ import (
/* /*
Simple gnmi request program. Use with cauton and leaf paths only. Simple gnmi request program. Use with cauton and leaf paths only.
Bootstrapping of pnd, device and transport simplified not idiomatic
*/ */
func main() { func main() {
log.SetLevel(log.DebugLevel) log.SetLevel(log.DebugLevel)
sbi := &nucleus.AristaOC{} sbi := &nucleus.AristaOC{}
transport := &nucleus.Gnmi{SetNode: sbi.SetNode()} device := &nucleus.Device{
device := nucleus.Device{ SBI: sbi,
Device: &schema.Device{},
SBI: sbi,
Config: nucleus.DeviceConfig{ Config: nucleus.DeviceConfig{
Uuid: uuid.New(), Uuid: uuid.New(),
Address: "localhost:9339", Address: "localhost:9339",
Username: "admin", Username: "admin",
Password: "arista", Password: "arista",
}, },
Transport: transport, Encoding: gpb.Encoding_PROTO,
} }
pnd := nucleus.NewPND("openconfig", sbi) pnd := nucleus.NewPND("openconfig", sbi)
if err := pnd.AddDevice(device); err != nil { if err := pnd.AddDevice(device); err != nil {
log.Fatal(err) log.Fatal(err)
} }
transport := &nucleus.Gnmi{SetNode: sbi.SetNode()}
cfg := &gnmi.Config{ cfg := &gnmi.Config{
Addr: device.Config.Address, Addr: device.Config.Address,
Password: device.Config.Password, Password: device.Config.Password,
Username: device.Config.Username, Username: device.Config.Username,
Encoding: gpb.Encoding_PROTO, Encoding: gpb.Encoding_PROTO,
} }
ctx := gnmi.NewContext(context.Background(), cfg) transport.SetConfig(cfg)
ctx = context.WithValue(ctx, "config", cfg)
device.Transport = transport
p := []string{"/interfaces/interface[name=en0]/state/name"} p := []string{"/interfaces/interface[name=en0]/state/name"}
errors := 0 errors := 0
for _, path := range p { for _, path := range p {
resp, err := device.Transport.Get(ctx, path) err := pnd.RequestAll(path)
if err != nil { if err != nil {
log.Debug(err) log.Debug(err)
errors++ errors++
break break
} }
if err := device.Add(resp); err != nil {
log.Debug(err)
errors++
}
} }
percentage := float64(errors) / float64(len(p)) * 100.0 percentage := float64(errors) / float64(len(p)) * 100.0
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"errors"
"flag" "flag"
"fmt" "fmt"
"math" "math"
...@@ -252,9 +253,14 @@ func NewContext(ctx context.Context, cfg *Config) context.Context { ...@@ -252,9 +253,14 @@ func NewContext(ctx context.Context, cfg *Config) context.Context {
// NewGetRequest returns a GetRequest for the given paths // NewGetRequest returns a GetRequest for the given paths
func NewGetRequest(ctx context.Context, paths [][]string, origin string) (*pb.GetRequest, error) { func NewGetRequest(ctx context.Context, paths [][]string, origin string) (*pb.GetRequest, error) {
val := ctx.Value("config")
cfg, ok := val.(*Config)
if !ok {
return nil, errors.New("invalid type assertion")
}
req := &pb.GetRequest{ req := &pb.GetRequest{
Path: make([]*pb.Path, len(paths)), Path: make([]*pb.Path, len(paths)),
Encoding: ctx.Value("Config").(*Config).Encoding, Encoding: cfg.Encoding,
} }
for i, p := range paths { for i, p := range paths {
gnmiPath, err := ParseGNMIElements(p) gnmiPath, err := ParseGNMIElements(p)
......
...@@ -44,10 +44,10 @@ func GetWithRequest(ctx context.Context, client pb.GNMIClient, ...@@ -44,10 +44,10 @@ func GetWithRequest(ctx context.Context, client pb.GNMIClient,
return nil return nil
} }
// Get sends a GetRequest to the given ciena. // Get sends a GetRequest to the given server.
func Get(ctx context.Context, client pb.GNMIClient, paths [][]string, func Get(ctx context.Context, client pb.GNMIClient, paths [][]string,
origin string) error { origin string) error {
req, err := NewGetRequest(paths, origin) req, err := NewGetRequest(ctx, paths, origin)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -2,21 +2,26 @@ package nucleus ...@@ -2,21 +2,26 @@ package nucleus
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
gpb "github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/ygot/ygot" "github.com/openconfig/ygot/ygot"
) )
type Device struct { type Device struct {
Device ygot.GoStruct // Device inherits properies of ygot.GoStruct
SBI SouthboundInterface ygot.GoStruct
Config DeviceConfig
// SBI is the device's southbound interface implementation
SBI SouthboundInterface
// Config is the device's config. Under revision
Config DeviceConfig
// Transport is the device's Transport implementation
Transport Transport Transport Transport
}
// Add adds a property to a device. Please // Encoding is the gNMI encoding. API boundary edge case
// use better naming in further develop // TODO: Move to transport, gNMI dependency
// Also all that Interface Call specific logic belongs to SBI! Encoding gpb.Encoding
func (d Device) Add(resp interface{}) error {
return d.Transport.ProcessResponse(resp, d.Device, d.SBI.Schema())
} }
type DeviceConfig struct { type DeviceConfig struct {
......
...@@ -15,14 +15,15 @@ import ( ...@@ -15,14 +15,15 @@ import (
type Gnmi struct { type Gnmi struct {
SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
RespChan chan *gpb.SubscribeResponse RespChan chan *gpb.SubscribeResponse
config *gnmi.Config
} }
func (g *Gnmi) SetConfig(interface{}) error { func (g *Gnmi) SetConfig(config *gnmi.Config) {
return nil g.config = config
} }
func (g *Gnmi) GetConfig() interface{} { func (g *Gnmi) GetConfig() *gnmi.Config {
return nil return g.config
} }
// interface satisfaction for now // interface satisfaction for now
...@@ -114,22 +115,21 @@ func (g *Gnmi) Capabilities(ctx context.Context) (interface{}, error) { ...@@ -114,22 +115,21 @@ func (g *Gnmi) Capabilities(ctx context.Context) (interface{}, error) {
// Get calls GNMI get // Get calls GNMI get
func (g *Gnmi) get(ctx context.Context, paths [][]string, origin string) (interface{}, error) { func (g *Gnmi) get(ctx context.Context, paths [][]string, origin string) (interface{}, error) {
req, err := gnmi.NewGetRequest(paths, origin) ctx = context.WithValue(ctx, "config", g.config)
req, err := gnmi.NewGetRequest(ctx, paths, origin)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return getWithRequest(ctx, req) return g.getWithRequest(ctx, req)
} }
// getWithRequest takes a fully formed GetRequest, performs the Get, // getWithRequest takes a fully formed GetRequest, performs the Get,
// and returns any response. // and returns any response.
func getWithRequest(ctx context.Context, req *gpb.GetRequest) (interface{}, error) { func (g *Gnmi) getWithRequest(ctx context.Context, req *gpb.GetRequest) (interface{}, error) {
cfg := ctx.Value("config").(*gnmi.Config) client, err := gnmi.Dial(g.config)
client, err := gnmi.Dial(cfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
req.Encoding = cfg.Encoding
resp, err := client.Get(ctx, req) resp, err := client.Get(ctx, req)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -140,7 +140,7 @@ func getWithRequest(ctx context.Context, req *gpb.GetRequest) (interface{}, erro ...@@ -140,7 +140,7 @@ func getWithRequest(ctx context.Context, req *gpb.GetRequest) (interface{}, erro
// Set calls GNMI set // Set calls GNMI set
func (g *Gnmi) set(ctx context.Context, setOps []*gnmi.Operation, func (g *Gnmi) set(ctx context.Context, setOps []*gnmi.Operation,
exts ...*gnmi_ext.Extension) error { exts ...*gnmi_ext.Extension) error {
client, err := gnmi.Dial(ctx.Value("config").(*gnmi.Config)) client, err := gnmi.Dial(g.config)
if err != nil { if err != nil {
return err return err
} }
...@@ -149,7 +149,7 @@ func (g *Gnmi) set(ctx context.Context, setOps []*gnmi.Operation, ...@@ -149,7 +149,7 @@ func (g *Gnmi) set(ctx context.Context, setOps []*gnmi.Operation,
// Subscribe calls GNMI subscribe // Subscribe calls GNMI subscribe
func (g *Gnmi) subscribe(ctx context.Context) error { func (g *Gnmi) subscribe(ctx context.Context) error {
client, err := gnmi.Dial(ctx.Value("config").(*gnmi.Config)) client, err := gnmi.Dial(g.config)
if err != nil { if err != nil {
return err return err
} }
......
package nucleus package nucleus
import ( import (
"context"
"github.com/google/uuid" "github.com/google/uuid"
) )
...@@ -10,21 +11,23 @@ type PrincipalNetworkDomain interface { ...@@ -10,21 +11,23 @@ type PrincipalNetworkDomain interface {
Destroy() error Destroy() error
AddSbi() error AddSbi() error
RemoveSbi() error RemoveSbi() error
AddDevice(Device) error AddDevice(*Device) error
RemoveDevice(uuid uuid.UUID) error RemoveDevice(uuid.UUID) error
Request(uuid.UUID, string) error
RequestAll(string) error
} }
type pndImplementation struct { type pndImplementation struct {
name string name string
sbi map[string]SouthboundInterface sbi map[string]SouthboundInterface
devices map[uuid.UUID]Device devices map[uuid.UUID]*Device
} }
//NewPND creates a Principle Network Domain //NewPND creates a Principle Network Domain
func NewPND(name string, sbi SouthboundInterface) PrincipalNetworkDomain { func NewPND(name string, sbi SouthboundInterface) PrincipalNetworkDomain {
sbic := make(map[string]SouthboundInterface) sbic := make(map[string]SouthboundInterface)
sbic["default"] = sbi sbic["default"] = sbi
devices := make(map[uuid.UUID]Device) devices := make(map[uuid.UUID]*Device)
return &pndImplementation{ return &pndImplementation{
name: name, name: name,
sbi: sbic, sbi: sbic,
...@@ -45,7 +48,7 @@ func (pnd *pndImplementation) RemoveSbi() error { ...@@ -45,7 +48,7 @@ func (pnd *pndImplementation) RemoveSbi() error {
return removeSbi() return removeSbi()
} }
func (pnd *pndImplementation) AddDevice(device Device) error { func (pnd *pndImplementation) AddDevice(device *Device) error {
return pnd.addDevice(device) return pnd.addDevice(device)
} }
...@@ -67,7 +70,7 @@ func removeSbi() error { ...@@ -67,7 +70,7 @@ func removeSbi() error {
return nil return nil
} }
func (pnd *pndImplementation) addDevice(device Device) error { func (pnd *pndImplementation) addDevice(device *Device) error {
pnd.devices[device.Config.Uuid] = device pnd.devices[device.Config.Uuid] = device
return nil return nil
} }
...@@ -76,3 +79,22 @@ func (pnd *pndImplementation) removeDevice(uuid uuid.UUID) error { ...@@ -76,3 +79,22 @@ func (pnd *pndImplementation) removeDevice(uuid uuid.UUID) error {
delete(pnd.devices, uuid) delete(pnd.devices, uuid)
return nil return nil
} }
func (pnd *pndImplementation) Request(uuid uuid.UUID, path string) error {
d := pnd.devices[uuid]
ctx := context.Background()
_, err := d.Transport.Get(ctx, path)
if err != nil {
return err
}
return nil
}
func (pnd *pndImplementation) RequestAll(path string) error {
for k := range pnd.devices {
if err := pnd.Request(k, path); err != nil {
return err
}
}
return nil
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment