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

demo fudanet kolloquium

parent 5e43849e
No related branches found
No related tags found
No related merge requests found
File added
No preview for this file type
......@@ -53,7 +53,8 @@ to quickly create a Cobra application.`,
if err != nil {
return err
}
return gnmidemo.Set(args[0], a, u, p)
args = append(args, a, u, p)
return gnmidemo.Set(args...)
},
}
......
......@@ -6,15 +6,19 @@ import (
"code.fbi.h-da.de/cocsn/gosdn/nucleus/util"
"code.fbi.h-da.de/danet/gnmi-demo/generated"
"context"
"errors"
"fmt"
"github.com/gogo/protobuf/proto"
"github.com/google/uuid"
gpb "github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/goyang/pkg/yang"
yutil "github.com/openconfig/ygot/util"
"github.com/openconfig/ygot/ygot"
"github.com/openconfig/ygot/ytypes"
log "github.com/sirupsen/logrus"
"os"
"os/signal"
"reflect"
"syscall"
"time"
)
......@@ -35,6 +39,7 @@ func setup(params ...string) error {
Encoding: 0,
}
transport, err = nucleus.NewGnmiTransport(opts)
transport.(*nucleus.Gnmi).Unmarshal = southbound.Unmarshal()
if err != nil {
return err
}
......@@ -42,10 +47,21 @@ func setup(params ...string) error {
}
func Set(params ...string) error {
if err := setup(params[1:]...); err != nil {
lenArgs := len(params) - 3
if err := setup(params[lenArgs:]...); err != nil {
return err
}
resp, err := transport.Set(context.Background())
path := gnmi.SplitPath(params[0])
req := []interface{}{
&gnmi.Operation{
Type: "update",
Origin: "",
Target: "",
Path: path,
Val: params[1],
},
}
resp, err := transport.Set(context.Background(), req...)
if err != nil {
return err
}
......@@ -85,7 +101,7 @@ func Get(params ...string) error {
}
func Subscribe(params ...string) error {
opts := &gnmi.SubscribeOptions{
o := &gnmi.SubscribeOptions{
UpdatesOnly: false,
Prefix: "",
Mode: "stream",
......@@ -99,7 +115,7 @@ func Subscribe(params ...string) error {
}
done := make(chan os.Signal, 1)
signal.Notify(done, syscall.SIGILL, syscall.SIGTERM)
ctx := context.WithValue(context.Background(), "opts", opts)
ctx := context.WithValue(context.Background(), "opts", o)
go func() {
if err := transport.Subscribe(ctx); err != nil {
log.Fatal(err)
......@@ -137,6 +153,86 @@ func (s sbi) Schema() *ytypes.Schema {
return schema
}
// Unmarshal injects OpenConfig specific model
// representation to the transport.
// Needed for type assertion.
func (s sbi) Unmarshal() func([]byte, []string, interface{}, ...ytypes.UnmarshalOpt) error {
return unmarshal
}
// unmarshal parses a root or 1st level gNMI response to a go struct
// Named return due to how recover works here
func unmarshal(bytes []byte, fields []string, goStruct interface{}, opt ...ytypes.UnmarshalOpt) (err error) {
defer func() {
if r := recover(); r != nil {
err = r.(error)
}
}()
switch l := len(fields); l {
case 0:
return openconfig.Unmarshal(bytes, goStruct.(*openconfig.Device), opt...)
case 1:
default:
return errors.New("fehler")
}
var c ygot.GoStruct
var field string
// Load SBI definition
d := openconfig.Device{}
c, field, err = iter(&d, fields)
if err != nil {
return
}
if err = openconfig.Unmarshal(bytes, c, opt...); err != nil {
return
}
reflect.ValueOf(goStruct.(*openconfig.Device)).Elem().FieldByName(field).Set(reflect.ValueOf(c))
return nil
}
// iter walks down the provided paths and initializes the ygot.GoStruct. It only works for
// the root level. Watch out for named returns here
// TODO(mk): Fix deeper layers
func iter(a ygot.GoStruct, fields []string) (b ygot.GoStruct, f string, err error) {
defer func() {
if r := recover(); r != nil {
err = r.(error)
}
}()
var c ygot.GoStruct
var configStruct reflect.Value
f = fields[0]
s := reflect.ValueOf(a).Elem()
h := s.FieldByName(f)
configStruct = reflect.New(h.Type())
// Pointer of field needs to be initialized.
// Very convoluted russian doll trick
// https://stackoverflow.com/a/57469950/4378176
// https://golang.org/src/encoding/json/decode.go?s#L474
// TODO(mk): Prettify
p2 := configStruct.Elem()
// If we have KeyHelperGoStruct we need make and modify map instead of plain struct
if p2.Kind() == reflect.Map {
p2.Set(reflect.MakeMap(p2.Type()))
configStruct.Elem().Set(p2)
if err := yutil.InsertIntoMapStructField(a, f, "", p2); err != nil {
panic(err)
}
} else {
configStruct.Elem().Set(reflect.New(p2.Type().Elem()))
b = configStruct.Elem().Interface().(ygot.GoStruct)
}
if len(fields) > 1 {
c, _, _ = iter(b, fields[1:])
} else {
return
}
reflect.ValueOf(b).Elem().FieldByName(f).Set(reflect.ValueOf(c))
return
}
func (s sbi) Id() uuid.UUID {
panic("implement me")
}
Source diff could not be displayed: it is too large. Options to address this: view the blob.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment