diff --git a/cmd/gnmi-capabilities/capabilities.go b/cmd/gnmi-capabilities/capabilities.go new file mode 100644 index 0000000000000000000000000000000000000000..de9475197ab197cd52fc3940c6b54f80670097ec --- /dev/null +++ b/cmd/gnmi-capabilities/capabilities.go @@ -0,0 +1,41 @@ +package main + +import ( + "code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi" + "code.fbi.h-da.de/cocsn/gosdn/nucleus" + "context" + "fmt" + gpb "github.com/openconfig/gnmi/proto/gnmi" + log "github.com/sirupsen/logrus" + "strings" +) + +func main() { + cfg := &gnmi.Config{ + Addr: "[2003:e6:1722:fed0:0:242:ac11:5]:6030", + Username: "admin", + Password: "arista", + Encoding: gpb.Encoding_JSON_IETF, + } + transport,err := nucleus.NewGnmiTransport(cfg) + if err != nil { + log.Error(err) + } + resp, err := transport.Capabilities(context.Background()) + if err != nil { + log.Error(err) + } + modelData := resp.(*gpb.CapabilityResponse).SupportedModels + b := strings.Builder{} + for _,elem := range modelData { + _, err := b.WriteString(elem.Name) + if err != nil { + log.Error(err) + } + _, err = b.WriteString("\n") + if err != nil { + log.Error(err) + } + } + fmt.Println(b.String()) +} diff --git a/cmd/gnmi/gnmi.go b/cmd/gnmi/gnmi.go index 65b5ecb51777b623df1eb29fc028506fe3d8f365..da537bf1c4d5060dac54646566f3976b4eca820e 100644 --- a/cmd/gnmi/gnmi.go +++ b/cmd/gnmi/gnmi.go @@ -15,7 +15,7 @@ import ( func main() { log.SetLevel(log.DebugLevel) - sbi := &nucleus.AristaOC{} + sbi := &nucleus.OpenConfig{} device := &nucleus.Device{ GoStruct: sbi.Schema().Root, SBI: sbi, @@ -42,10 +42,11 @@ func main() { log.Fatal(err) } transport.SetNode = sbi.SetNode() + transport.Unmarshal = sbi.Unmarshal() device.Transport = transport - p := []string{"/interfaces/interface/name"} + p := []string{"/interfaces"} errors := 0 for _, path := range p { err := pnd.RequestAll(path) diff --git a/nucleus/controller.go b/nucleus/controller.go index 7a18b975d7b2d377a47dcc7ddfa7bd4b6d487356..d4bd7cb508af685fbf32bd14d59b9e8ea0bbe9ff 100644 --- a/nucleus/controller.go +++ b/nucleus/controller.go @@ -57,7 +57,7 @@ func (c *Core) AttachDatabase() { // CreateSouthboundInterfaces initializes the controller with its supported SBIs func (c *Core) CreateSouthboundInterfaces() error { - if err := c.sbic.add(&AristaOC{id: uuid.New()}); err != nil { + if err := c.sbic.add(&Arista{id: uuid.New()}); err != nil { return err } if err := c.sbic.add(&OpenConfig{id: uuid.New()}); err != nil { diff --git a/nucleus/gnmi_transport.go b/nucleus/gnmi_transport.go index 196f815c58bf905da69bfb6b2dfc2469d4bcc23a..1adf8dd1230d451b9c63b775800687b0cd680e92 100644 --- a/nucleus/gnmi_transport.go +++ b/nucleus/gnmi_transport.go @@ -29,8 +29,6 @@ func NewGnmiTransport(config *gnmi.Config) (*Gnmi, error) { return nil, err } return &Gnmi{ - SetNode: nil, - RespChan: nil, config: config, client: c, }, nil @@ -38,6 +36,7 @@ func NewGnmiTransport(config *gnmi.Config) (*Gnmi, error) { type Gnmi struct { SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error + Unmarshal func([]byte, string, interface{}, ...ytypes.UnmarshalOpt) error RespChan chan *gpb.SubscribeResponse config *gnmi.Config client gpb.GNMIClient @@ -81,7 +80,6 @@ func (g *Gnmi) Type() string { // ProcessResponse takes a gNMI response and serializes the contents to the root struct. func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Schema) error { models := s.SchemaTree - opts := []ytypes.SetNodeOpt{&ytypes.InitMissingElements{}, &ytypes.TolerateJSONInconsistencies{}} r := resp.(*gpb.GetResponse) rn := r.Notification for _, msg := range rn { @@ -97,10 +95,18 @@ func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Sch } } modelKey := extractModelKey(fullPath) - log.Debug(modelKey) + schema := models[modelKey] - schema := models["Device"] + val,ok := update.Val.Value.(*gpb.TypedValue_JsonIetfVal) + if ok { + opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}} + if err := g.Unmarshal(val.JsonIetfVal,fullPath.String(), root, opts...); err != nil { + return err + } + return nil + } + opts := []ytypes.SetNodeOpt{&ytypes.InitMissingElements{}, &ytypes.TolerateJSONInconsistencies{}} if err := g.SetNode(schema, root, update.Path, update.Val, opts...); err != nil { return err } @@ -116,7 +122,7 @@ func extractModelKey(path *gpb.Path) string { var b strings.Builder delim := "_" b.WriteString("OpenconfigInterfaces") - for i := 0; i < len(path.Elem)-1; i++ { + for i := 0; i < len(path.Elem); i++ { pathElement := path.Elem[i] b.WriteString(delim) b.WriteString(strings.Title(pathElement.Name)) @@ -139,6 +145,8 @@ func gnmiFullPath(prefix, path *gpb.Path) (*gpb.Path, error) { // Capabilities calls GNMI capabilities func (g *Gnmi) Capabilities(ctx context.Context) (interface{}, error) { + ctx = gnmi.NewContext(ctx, g.config) + ctx = context.WithValue(ctx, "config", g.config) resp, err := g.client.Capabilities(ctx, &gpb.CapabilityRequest{}) if err != nil { return nil, err @@ -162,10 +170,10 @@ func (g *Gnmi) get(ctx context.Context, paths [][]string, origin string) (interf func (g *Gnmi) getWithRequest(ctx context.Context, req *gpb.GetRequest) (interface{}, error) { resp, err := g.client.Get(ctx, req) if tapProto { - if err := util.Write(req, "req-"+time.Now().String()); err != nil { + if err := util.Write(req, "get-req-"+time.Now().String()); err != nil { log.Errorf("error while writing request: %v", err) } - if err := util.Write(resp, "resp-"+time.Now().String()); err != nil { + if err := util.Write(resp, "get-resp-"+time.Now().String()); err != nil { log.Errorf("error while writing request: %v", err) } } diff --git a/nucleus/gnmi_transport_test.go b/nucleus/gnmi_transport_test.go index 6e0a426f4f936d8f865661e38ae83b93adedd20b..3f9fdfa564752ec84cf1113ff09f4bed17341df8 100644 --- a/nucleus/gnmi_transport_test.go +++ b/nucleus/gnmi_transport_test.go @@ -282,7 +282,7 @@ func TestGnmi_ProcessResponse(t *testing.T) { }{ { name: "Arista Full Node", - fields: fields{Sbi: &AristaOC{}}, + fields: fields{Sbi: &Arista{}}, args: args{ path: "../test/resp-full-node", root: &arista.Device{}, @@ -291,7 +291,7 @@ func TestGnmi_ProcessResponse(t *testing.T) { }, { name: "Arista Interfaces Wildcard", - fields: fields{Sbi: &AristaOC{}}, + fields: fields{Sbi: &Arista{}}, args: args{ path: "../test/resp-interfaces-wildcard", root: &arista.Device{},