Skip to content
Snippets Groups Projects
southbound.go 4.86 KiB
Newer Older
  • Learn to ignore specific revisions
  • Manuel Kieweg's avatar
    Manuel Kieweg committed
    package nucleus
    
    
    import (
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound"
    	"code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"code.fbi.h-da.de/danet/yang-models/generated/openconfig"
    
    	"github.com/google/uuid"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	gpb "github.com/openconfig/gnmi/proto/gnmi"
    	"github.com/openconfig/goyang/pkg/yang"
    
    	"github.com/openconfig/ygot/ygot"
    
    	"github.com/openconfig/ygot/ytypes"
    
    	log "github.com/sirupsen/logrus"
    
    var csbi *Csbi
    
    func init() {
    	csbi = &Csbi{id: uuid.New()}
    }
    
    
    // NewSBI creates a SouthboundInterface of a given type.
    
    func NewSBI(southbound spb.Type, sbUUID ...uuid.UUID) (southbound.SouthboundInterface, error) {
    
    	var id uuid.UUID
    
    	if len(sbUUID) == 0 {
    		id = uuid.New()
    	} else {
    		id = sbUUID[0]
    	}
    
    
    	switch southbound {
    
    	case spb.Type_TYPE_OPENCONFIG:
    
    	default:
    
    		return nil, errors.ErrTypeNotSupported{Type: southbound}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // OpenConfig is the implementation of an OpenConfig SBI.
    // The struct holds the YANG schema and a function that
    // returns an SBI specific SetNode function.
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    type OpenConfig struct {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	schema *ytypes.Schema
    
    	id     uuid.UUID
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // SbiIdentifier returns the string representation of
    // the SBI
    // deprecated
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func (oc *OpenConfig) SbiIdentifier() string {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	return "openconfig"
    }
    
    
    // Schema returns a ygot generated openconfig Schema as ytypes.Schema
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func (oc *OpenConfig) Schema() *ytypes.Schema {
    	schema, err := openconfig.Schema()
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		log.Fatal(err)
    	}
    	return schema
    }
    
    // SetNode injects OpenConfig specific model representation to the transport.
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // Needed for type assertion.
    
    func (oc *OpenConfig) SetNode(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error {
    	return ytypes.SetNode(schema, root.(*openconfig.Device), path, val, opts...)
    
    // Unmarshal injects OpenConfig specific model representation to the transport.
    
    // Needed for type assertion.
    
    func (oc *OpenConfig) Unmarshal(bytes []byte, path *gpb.Path, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
    	return unmarshal(oc.Schema(), bytes, path, goStruct, opt...)
    
    //unmarshal parses a gNMI response to a go struct.
    func unmarshal(schema *ytypes.Schema, bytes []byte, path *gpb.Path, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
    
    	defer func() {
    		if r := recover(); r != nil {
    
    			log.Error(r.(error))
    
    	}()
    
    	// Load SBI definition
    
    	root, err := ygot.DeepCopy(schema.Root)
    
    	if err != nil {
    
    		return err
    
    	validatedDeepCopy, ok := root.(ygot.ValidatedGoStruct)
    	if !ok {
    
    		return &errors.ErrInvalidTypeAssertion{
    			Value: root,
    			Type:  (*ygot.ValidatedGoStruct)(nil),
    		}
    
    	// returns the node we want to fill with the data contained in 'bytes',
    	// using the specified 'path'.
    	createdNode, _, err := ytypes.GetOrCreateNode(schema.RootSchema(), validatedDeepCopy, path)
    	if err != nil {
    		return err
    	}
    	validatedCreatedNode, ok := createdNode.(ygot.ValidatedGoStruct)
    	if !ok {
    
    		return &errors.ErrInvalidTypeAssertion{
    			Value: createdNode,
    			Type:  (*ygot.ValidatedGoStruct)(nil),
    		}
    
    	if err := openconfig.Unmarshal(bytes, validatedCreatedNode, opt...); err != nil {
    
    		return err
    	}
    
    
    	opts := []ygot.MergeOpt{&ygot.MergeOverwriteExistingFields{}}
    	return ygot.MergeStructInto(goStruct, validatedDeepCopy, opts...)
    
    // ID returns the ID of the OpenConfig SBI
    func (oc *OpenConfig) ID() uuid.UUID {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    
    // Type returns the Southbound's type
    
    func (oc *OpenConfig) Type() spb.Type { return spb.Type_TYPE_OPENCONFIG }
    
    
    // Csbi is a stub for the containerised SBI functionality.
    // It holds the standard goSDN OPENCONFIG schema for minimum
    // compatibility
    type Csbi struct {
    	schema *ytypes.Schema
    	id     uuid.UUID
    }
    
    // SbiIdentifier returns the identifier as a
    func (csbi *Csbi) SbiIdentifier() string {
    	return "csbi"
    }
    
    // SetNode injects schema specific model representation to the transport.
    // Needed for type assertion.
    func (csbi *Csbi) SetNode(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error {
    	return ytypes.SetNode(schema, root.(*openconfig.Device), path, val, opts...)
    }
    
    // Unmarshal injects schema specific model representation to the transport.
    // Needed for type assertion.
    
    func (csbi *Csbi) Unmarshal(bytes []byte, path *gpb.Path, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
    
    	oc := OpenConfig{}
    
    	return unmarshal(oc.Schema(), bytes, path, goStruct, opt...)
    
    }
    
    // Schema is holding the default OpenConfig schema for minimal compatibility
    // to gosdn interfaces
    func (csbi *Csbi) Schema() *ytypes.Schema {
    	schema, err := openconfig.Schema()
    	csbi.schema = schema
    	if err != nil {
    		log.Fatal(err)
    	}
    	return schema
    }
    
    // ID returns the Southbound's UUID
    func (csbi *Csbi) ID() uuid.UUID {
    	return csbi.id
    }
    
    // Type returns the Southbound's type
    func (csbi *Csbi) Type() spb.Type {
    
    	return spb.Type_TYPE_CONTAINERISED