diff --git a/cmd/gnmi/gnmi.go b/cmd/gnmi/gnmi.go index 21902da124c9ee07229b37293db009056f0c21e1..65d3640ea79c3710f696b62fd43132618d6989fb 100644 --- a/cmd/gnmi/gnmi.go +++ b/cmd/gnmi/gnmi.go @@ -3,8 +3,6 @@ package main import ( "code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi" "code.fbi.h-da.de/cocsn/gosdn/nucleus" - schema "code.fbi.h-da.de/cocsn/yang-models/generated/arista" - "context" "github.com/google/uuid" gpb "github.com/openconfig/gnmi/proto/gnmi" log "github.com/sirupsen/logrus" @@ -12,50 +10,47 @@ import ( /* Simple gnmi request program. Use with cauton and leaf paths only. + Bootstrapping of pnd, device and transport simplified not idiomatic */ func main() { log.SetLevel(log.DebugLevel) sbi := &nucleus.AristaOC{} - transport := &nucleus.Gnmi{SetNode: sbi.SetNode()} - device := nucleus.Device{ - Device: &schema.Device{}, - SBI: sbi, + device := &nucleus.Device{ + SBI: sbi, Config: nucleus.DeviceConfig{ Uuid: uuid.New(), Address: "localhost:9339", Username: "admin", Password: "arista", }, - Transport: transport, + Encoding: gpb.Encoding_PROTO, } pnd := nucleus.NewPND("openconfig", sbi) if err := pnd.AddDevice(device); err != nil { log.Fatal(err) } + transport := &nucleus.Gnmi{SetNode: sbi.SetNode()} cfg := &gnmi.Config{ Addr: device.Config.Address, Password: device.Config.Password, Username: device.Config.Username, Encoding: gpb.Encoding_PROTO, } - ctx := gnmi.NewContext(context.Background(), cfg) - ctx = context.WithValue(ctx, "config", cfg) + transport.SetConfig(cfg) + + device.Transport = transport p := []string{"/interfaces/interface[name=en0]/state/name"} errors := 0 for _, path := range p { - resp, err := device.Transport.Get(ctx, path) + err := pnd.RequestAll(path) if err != nil { log.Debug(err) errors++ break } - if err := device.Add(resp); err != nil { - log.Debug(err) - errors++ - } } percentage := float64(errors) / float64(len(p)) * 100.0 diff --git a/forks/goarista/gnmi/client.go b/forks/goarista/gnmi/client.go index d4a9958baf56c494705949b3deedb61075ae5e65..bfb404ada10a59f474c993e184a1ade785ef63bf 100644 --- a/forks/goarista/gnmi/client.go +++ b/forks/goarista/gnmi/client.go @@ -8,6 +8,7 @@ import ( "context" "crypto/tls" "crypto/x509" + "errors" "flag" "fmt" "math" @@ -252,9 +253,14 @@ func NewContext(ctx context.Context, cfg *Config) context.Context { // NewGetRequest returns a GetRequest for the given paths 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{ Path: make([]*pb.Path, len(paths)), - Encoding: ctx.Value("Config").(*Config).Encoding, + Encoding: cfg.Encoding, } for i, p := range paths { gnmiPath, err := ParseGNMIElements(p) diff --git a/forks/goarista/gnmi/operation.go b/forks/goarista/gnmi/operation.go index ef506ac5e99e824fc4adc4cb34805e2b4ed27dd1..15ab81fcafee0d693a58bcc265244df7d75de164 100644 --- a/forks/goarista/gnmi/operation.go +++ b/forks/goarista/gnmi/operation.go @@ -44,10 +44,10 @@ func GetWithRequest(ctx context.Context, client pb.GNMIClient, 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, origin string) error { - req, err := NewGetRequest(paths, origin) + req, err := NewGetRequest(ctx, paths, origin) if err != nil { return err } diff --git a/nucleus/device.go b/nucleus/device.go index 1ab2f74a04978bbbe71eaea8bd46e8821c7c3eaa..73069aeba8e293e9ba16023c042c224695a539d1 100644 --- a/nucleus/device.go +++ b/nucleus/device.go @@ -2,21 +2,26 @@ package nucleus import ( "github.com/google/uuid" + gpb "github.com/openconfig/gnmi/proto/gnmi" "github.com/openconfig/ygot/ygot" ) type Device struct { - Device ygot.GoStruct - SBI SouthboundInterface - Config DeviceConfig + // Device inherits properies of ygot.GoStruct + ygot.GoStruct + + // 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 -} -// Add adds a property to a device. Please -// use better naming in further develop -// Also all that Interface Call specific logic belongs to SBI! -func (d Device) Add(resp interface{}) error { - return d.Transport.ProcessResponse(resp, d.Device, d.SBI.Schema()) + // Encoding is the gNMI encoding. API boundary edge case + // TODO: Move to transport, gNMI dependency + Encoding gpb.Encoding } type DeviceConfig struct { diff --git a/nucleus/gnmi_transport.go b/nucleus/gnmi_transport.go index b3921329db044ec15235d12f7a57d76331291b4b..2c0ad0c0178cfa816a97a0e4f68852b50182cd7c 100644 --- a/nucleus/gnmi_transport.go +++ b/nucleus/gnmi_transport.go @@ -15,14 +15,15 @@ import ( type Gnmi struct { SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error RespChan chan *gpb.SubscribeResponse + config *gnmi.Config } -func (g *Gnmi) SetConfig(interface{}) error { - return nil +func (g *Gnmi) SetConfig(config *gnmi.Config) { + g.config = config } -func (g *Gnmi) GetConfig() interface{} { - return nil +func (g *Gnmi) GetConfig() *gnmi.Config { + return g.config } // interface satisfaction for now @@ -114,22 +115,21 @@ func (g *Gnmi) Capabilities(ctx context.Context) (interface{}, error) { // Get calls GNMI get 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 { return nil, err } - return getWithRequest(ctx, req) + return g.getWithRequest(ctx, req) } // getWithRequest takes a fully formed GetRequest, performs the Get, // and returns any response. -func getWithRequest(ctx context.Context, req *gpb.GetRequest) (interface{}, error) { - cfg := ctx.Value("config").(*gnmi.Config) - client, err := gnmi.Dial(cfg) +func (g *Gnmi) getWithRequest(ctx context.Context, req *gpb.GetRequest) (interface{}, error) { + client, err := gnmi.Dial(g.config) if err != nil { return nil, err } - req.Encoding = cfg.Encoding resp, err := client.Get(ctx, req) if err != nil { return nil, err @@ -140,7 +140,7 @@ func getWithRequest(ctx context.Context, req *gpb.GetRequest) (interface{}, erro // Set calls GNMI set func (g *Gnmi) set(ctx context.Context, setOps []*gnmi.Operation, exts ...*gnmi_ext.Extension) error { - client, err := gnmi.Dial(ctx.Value("config").(*gnmi.Config)) + client, err := gnmi.Dial(g.config) if err != nil { return err } @@ -149,7 +149,7 @@ func (g *Gnmi) set(ctx context.Context, setOps []*gnmi.Operation, // Subscribe calls GNMI subscribe 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 { return err } diff --git a/nucleus/principalNetworkDomain.go b/nucleus/principalNetworkDomain.go index fd54a00abdd9a60e65859978582eb502dc06854d..6d988fe9a88b7b8a4ba95ede08c5059a2765d912 100644 --- a/nucleus/principalNetworkDomain.go +++ b/nucleus/principalNetworkDomain.go @@ -1,6 +1,7 @@ package nucleus import ( + "context" "github.com/google/uuid" ) @@ -10,21 +11,23 @@ type PrincipalNetworkDomain interface { Destroy() error AddSbi() error RemoveSbi() error - AddDevice(Device) error - RemoveDevice(uuid uuid.UUID) error + AddDevice(*Device) error + RemoveDevice(uuid.UUID) error + Request(uuid.UUID, string) error + RequestAll(string) error } type pndImplementation struct { name string sbi map[string]SouthboundInterface - devices map[uuid.UUID]Device + devices map[uuid.UUID]*Device } //NewPND creates a Principle Network Domain func NewPND(name string, sbi SouthboundInterface) PrincipalNetworkDomain { sbic := make(map[string]SouthboundInterface) sbic["default"] = sbi - devices := make(map[uuid.UUID]Device) + devices := make(map[uuid.UUID]*Device) return &pndImplementation{ name: name, sbi: sbic, @@ -45,7 +48,7 @@ func (pnd *pndImplementation) RemoveSbi() error { return removeSbi() } -func (pnd *pndImplementation) AddDevice(device Device) error { +func (pnd *pndImplementation) AddDevice(device *Device) error { return pnd.addDevice(device) } @@ -67,7 +70,7 @@ func removeSbi() error { return nil } -func (pnd *pndImplementation) addDevice(device Device) error { +func (pnd *pndImplementation) addDevice(device *Device) error { pnd.devices[device.Config.Uuid] = device return nil } @@ -76,3 +79,22 @@ func (pnd *pndImplementation) removeDevice(uuid uuid.UUID) error { delete(pnd.devices, uuid) 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 +}