diff --git a/cmd/gnmi/gnmi.go b/cmd/gnmi/gnmi.go index 73ba7e4e742aedc38e7107843f35c13de303a127..32b987ef890785f4e8078c7fa1f531ee7247b00f 100644 --- a/cmd/gnmi/gnmi.go +++ b/cmd/gnmi/gnmi.go @@ -3,18 +3,19 @@ package main import ( "code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi" "code.fbi.h-da.de/cocsn/gosdn/nucleus" - "code.fbi.h-da.de/cocsn/yang-models/generated/openconfig" + "code.fbi.h-da.de/cocsn/gosdn/nucleus/util" + schema "code.fbi.h-da.de/cocsn/yang-models/generated/arista" "context" - "fmt" "github.com/google/uuid" log "github.com/sirupsen/logrus" ) func main() { log.SetLevel(log.DebugLevel) - sbi := &nucleus.OpenConfig{} + sbi := &nucleus.AristaOC{} + transport := &nucleus.Gnmi{SetNode: sbi.SetNode()} device := nucleus.Device{ - Device: &openconfig.Device{}, + Device: &schema.Device{}, SBI: sbi, Config: nucleus.DeviceConfig{ Uuid: uuid.New(), @@ -22,6 +23,7 @@ func main() { Username: "admin", Password: "arista", }, + Transport: transport, } pnd := nucleus.NewPND("openconfig", sbi) if err := pnd.AddDevice(device); err != nil { @@ -36,14 +38,25 @@ func main() { ctx := gnmi.NewContext(context.Background(), cfg) ctx = context.WithValue(ctx, "config", cfg) - paths := []string{"/interfaces/interface[name=*]/name"} - req, err := gnmi.NewGetRequest(gnmi.SplitPaths(paths), "") - resp, err := nucleus.GetWithRequest(ctx, req) - if err != nil { - log.Fatal(err) - } - if err := device.Add(resp); err != nil { - panic(err) + paths := util.NewPaths() + paths.ParseSchema(sbi.Schema(), "device") + p := paths.StringBuilder() + errors := 0 + for _,path := range p { + req, err := gnmi.NewGetRequest(gnmi.SplitPaths([]string{path}), "") + resp, err := nucleus.GetWithRequest(ctx, req) + if err != nil { + log.Debug(err) + errors++ + break + } + if err := device.Add(resp); err != nil { + log.Debug(err) + errors++ + } } - fmt.Println(device.Config) + + percentage := errors / len(p) * 100 + log.Debugf("%v errors", errors) + log.Debugf("%v percent failed", percentage) } diff --git a/nucleus/device.go b/nucleus/device.go index 78bb3fae47715b982bb3fd663ccf545981be17b1..1ab2f74a04978bbbe71eaea8bd46e8821c7c3eaa 100644 --- a/nucleus/device.go +++ b/nucleus/device.go @@ -1,11 +1,8 @@ package nucleus import ( - "code.fbi.h-da.de/cocsn/yang-models/generated/openconfig" "github.com/google/uuid" - pb "github.com/openconfig/gnmi/proto/gnmi" "github.com/openconfig/ygot/ygot" - "github.com/openconfig/ygot/ytypes" ) type Device struct { @@ -19,23 +16,7 @@ type Device struct { // use better naming in further develop // Also all that Interface Call specific logic belongs to SBI! func (d Device) Add(resp interface{}) error { - s, err := d.SBI.Schema() - if err != nil { - return err - } - models := s.SchemaTree - opts := []ytypes.SetNodeOpt{&ytypes.InitMissingElements{}, &ytypes.TolerateJSONInconsistencies{}} - r := resp.(*pb.GetResponse) - rn := r.Notification - for _, msg := range rn { - for _, val := range msg.Update { - schema := models["Device"] - if err := ytypes.SetNode(schema, d.Device.(*openconfig.Device), val.Path, val.Val, opts...); err != nil { - return err - } - } - } - return nil + return d.Transport.ProcessResponse(resp, d.Device, d.SBI.Schema()) } type DeviceConfig struct { diff --git a/nucleus/gnmi_transport.go b/nucleus/gnmi_transport.go index 867fdea28c1f39d163cc2dfe4318fae8e3bfe32a..40e7b64c2de4109aac247c3bd29bc7c633ad28db 100644 --- a/nucleus/gnmi_transport.go +++ b/nucleus/gnmi_transport.go @@ -3,13 +3,15 @@ package nucleus import ( "code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi" "context" - "github.com/google/uuid" - "github.com/openconfig/gnmi/proto/gnmi_ext" - gpb "github.com/openconfig/gnmi/proto/gnmi" + "github.com/openconfig/gnmi/proto/gnmi_ext" + "github.com/openconfig/goyang/pkg/yang" + "github.com/openconfig/ygot/ytypes" ) -type Gnmi uuid.UUID +type Gnmi struct { + SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error +} func (g *Gnmi) SetConfig(interface{}) error { return nil @@ -19,6 +21,32 @@ func (g *Gnmi) GetConfig() interface{} { return nil } +// interface satisfaction for now +// TODO: Convert to meaningfiul calls +func (g *Gnmi)Get(ctx context.Context, params ...string) (interface{}, error){return nil, nil} +func (g *Gnmi)Set(ctx context.Context, params ...string) (interface{}, error){return nil, nil} +func (g *Gnmi)Subscribe(ctx context.Context, params ...string) error{return nil} + +func (g *Gnmi)Type() string { + return "gnmi" +} + +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 { + for _, val := range msg.Update { + schema := models["Device"] + if err := g.SetNode(schema, root, val.Path, val.Val, opts...); err != nil { + return err + } + } + } + return nil +} + // Capabilities calls GNMI capabilities func (g *Gnmi) Capabilities(ctx context.Context) (interface{}, error) { client, err := gnmi.Dial(ctx.Value("config").(*gnmi.Config)) @@ -33,7 +61,7 @@ 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) { +func (g *Gnmi) get(ctx context.Context, paths [][]string, origin string) (interface{}, error) { req, err := gnmi.NewGetRequest(paths, origin) if err != nil { return nil, err @@ -56,7 +84,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, +func (g *Gnmi) set(ctx context.Context, setOps []*gnmi.Operation, exts ...*gnmi_ext.Extension) error { client, err := gnmi.Dial(ctx.Value("config").(*gnmi.Config)) if err != nil { @@ -66,7 +94,7 @@ func (g *Gnmi) Set(ctx context.Context, setOps []*gnmi.Operation, } // Subscribe calls GNMI subscribe -func (g *Gnmi) Subscribe(ctx context.Context, subscribeOptions *gnmi.SubscribeOptions, +func (g *Gnmi) subscribe(ctx context.Context, subscribeOptions *gnmi.SubscribeOptions, respChan chan<- *gpb.SubscribeResponse) error { client, err := gnmi.Dial(ctx.Value("config").(*gnmi.Config)) if err != nil { diff --git a/nucleus/southbound.go b/nucleus/southbound.go index e908f41d17b114b92f3cb814ad92f0dbe41efb92..1e27e79103a4c24ca9b9a9bbc203134618501770 100644 --- a/nucleus/southbound.go +++ b/nucleus/southbound.go @@ -1,8 +1,11 @@ package nucleus import ( - "code.fbi.h-da.de/cocsn/gosdn/nucleus/util" + "code.fbi.h-da.de/cocsn/yang-models/generated/arista" "code.fbi.h-da.de/cocsn/yang-models/generated/openconfig" + log "github.com/golang/glog" + gpb "github.com/openconfig/gnmi/proto/gnmi" + "github.com/openconfig/goyang/pkg/yang" "github.com/openconfig/ygot/ytypes" ) @@ -12,7 +15,8 @@ type SouthboundInterface interface { // Deprecated SbiIdentifier() string - Schema() (*ytypes.Schema, error) + SetNode() func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error + Schema() *ytypes.Schema } type Tapi struct { @@ -27,21 +31,45 @@ func (oc *OpenConfig) SbiIdentifier() string { return "openconfig" } -func (oc *OpenConfig) Schema() (*ytypes.Schema, error) { - return openconfig.Schema() -} - -func (oc *OpenConfig) OpenconfigInterfaces(device Device) { - resp, err := oc.transport.Get(nil, nil...) +func (oc *OpenConfig) Schema() *ytypes.Schema { + schema, err := openconfig.Schema() if err != nil { + log.Fatal(err) + } + return schema +} +func (oc *OpenConfig)SetNode() func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error { + return func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error { + if err := ytypes.SetNode(schema, root.(*openconfig.Device), path, val, opts...); err != nil { + return err + } + return nil } - device.Add(resp) } -func (oc *OpenConfig) GetFullDeviceInfo(device Device) error { - paths := util.NewPaths() - paths.ParseSchema(oc.schema, "device") +type AristaOC struct { + transport Transport + schema *ytypes.Schema +} + +func (oc *AristaOC) SbiIdentifier() string { + return "arista" +} - return nil +func (oc *AristaOC) Schema() *ytypes.Schema { + schema, err := arista.Schema() + if err != nil { + log.Fatal(err) + } + return schema +} + +func (oc *AristaOC)SetNode() func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error { + return func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error { + if err := ytypes.SetNode(schema, root.(*arista.Device), path, val, opts...); err != nil { + return err + } + return nil + } } diff --git a/nucleus/transport.go b/nucleus/transport.go index 809ddd603ba4143c97e1fead882b6c620ddb8efe..b3e397890bbd00ccd6082b1dd344f142ccdcc1d6 100644 --- a/nucleus/transport.go +++ b/nucleus/transport.go @@ -3,6 +3,7 @@ package nucleus import ( "bytes" "context" + "github.com/openconfig/ygot/ytypes" "io" ) @@ -13,6 +14,8 @@ type Transport interface { Get(ctx context.Context, params ...string) (interface{}, error) Set(ctx context.Context, params ...string) (interface{}, error) Subscribe(ctx context.Context, params ...string) error + Type() string + ProcessResponse(resp interface{},root interface{}, models *ytypes.Schema) error } // YANGConsumer is a auxillary type to redirect the response