Skip to content
Snippets Groups Projects
principalNetworkDomain.go 4.92 KiB
Newer Older
  • Learn to ignore specific revisions
  • package nucleus
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    import (
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
    
    	log "github.com/sirupsen/logrus"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"github.com/google/uuid"
    )
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // PrincipalNetworkDomain provides an
    // interface for PND implementations
    type PrincipalNetworkDomain interface {
    	Destroy() error
    
    	AddSbi(interface{}) error
    	RemoveSbi(uuid.UUID) error
    	AddDevice(interface{}) error
    
    	RemoveDevice(uuid.UUID) error
    
    	Request(uuid.UUID, string) error
    	RequestAll(string) error
    
    	MarshalDevice(uuid.UUID) (string, error)
    	ContainsDevice(uuid.UUID) bool
    
    	GetSBIs() interface{}
    	Id() uuid.UUID
    
    type pndImplementation struct {
    
    	name        string
    	description string
    
    	sbic        sbiStore
    	devices     deviceStore
    
    // NewPND creates a Principle Network Domain
    
    func NewPND(name, description string, id uuid.UUID, sbi SouthboundInterface) (PrincipalNetworkDomain, error) {
    
    	pnd := &pndImplementation{
    		name:        name,
    		description: description,
    		sbic:        sbiStore{store{}},
    		devices:     deviceStore{store{}},
    		id:          id,
    	}
    	if err := pnd.sbic.add(sbi); err != nil {
    		return nil, &ErrAlreadyExists{item: sbi}
    	}
    	return pnd, nil
    }
    
    func (pnd *pndImplementation) Id() uuid.UUID {
    	return pnd.id
    
    // GetName returns the name of the PND
    
    Malte Bauch's avatar
    Malte Bauch committed
    func (pnd *pndImplementation) GetName() string {
    
    	return pnd.name
    
    // ContainsDevice checks if the given device uuid is registered for this PND
    
    func (pnd *pndImplementation) ContainsDevice(id uuid.UUID) bool {
    	return pnd.devices.exists(id)
    
    // GetDescription returns the current description of the PND
    
    func (pnd *pndImplementation) GetDescription() string {
    
    	return pnd.description
    
    // GetSBIs returns the registered SBIs
    
    func (pnd *pndImplementation) GetSBIs() interface{} {
    	return &pnd.sbic
    
    // Destroy destroys the PND
    
    func (pnd *pndImplementation) Destroy() error {
    	return destroy()
    }
    
    
    // AddSbi adds a SBI to the PND which will be supported
    
    func (pnd *pndImplementation) AddSbi(sbi interface{}) error {
    	s, ok := sbi.(SouthboundInterface)
    	if !ok {
    		return &ErrInvalidTypeAssertion{
    			v: sbi,
    			t: "Device",
    		}
    	}
    	return pnd.addSbi(s)
    
    // AddSbi removes a SBI from the PND
    // TODO: this should to recursivly through
    // devices and remove the devices using
    // this SBI
    
    func (pnd *pndImplementation) RemoveSbi(id uuid.UUID) error {
    	return pnd.removeSbi(id)
    
    Malte Bauch's avatar
    Malte Bauch committed
    //AddDevice adds a new device to the PND
    
    func (pnd *pndImplementation) AddDevice(device interface{}) error {
    	d, ok := device.(*Device)
    	if !ok {
    		return &ErrInvalidTypeAssertion{
    			v: device,
    			t: "Device",
    		}
    	}
    	return pnd.addDevice(d)
    
    // RemoveDevice removes a device from the PND
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func (pnd *pndImplementation) RemoveDevice(uuid uuid.UUID) error {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	return pnd.removeDevice(uuid)
    
    // Actual implementation, bind to struct if
    // neccessary
    func destroy() error {
    	return nil
    }
    
    
    Malte Bauch's avatar
    Malte Bauch committed
    func (pnd *pndImplementation) addSbi(sbi SouthboundInterface) error {
    
    	return pnd.sbic.add(sbi)
    
    func (pnd *pndImplementation) removeSbi(id uuid.UUID) error {
    	return pnd.sbic.delete(id)
    
    func (pnd *pndImplementation) addDevice(device *Device) error {
    
    	return pnd.devices.add(device)
    
    func (pnd *pndImplementation) getDevice(id uuid.UUID) (*Device, error) {
    	return pnd.devices.get(id)
    
    func (pnd *pndImplementation) removeDevice(id uuid.UUID) error {
    	return pnd.devices.delete(id)
    
    func (pnd *pndImplementation) MarshalDevice(uuid uuid.UUID) (string, error) {
    
    	d, err := pnd.getDevice(uuid)
    	if err != nil {
    		return "", err
    	}
    	jsonTree, err := json.MarshalIndent(d.GoStruct, "", "\t")
    
    	if err != nil {
    		return "", err
    	}
    
    	log.WithFields(log.Fields{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		"pnd":    pnd.id,
    
    		"device": uuid,
    	}).Info("marshalled device")
    
    	return string(jsonTree), nil
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // Request sends a get request to a specific device
    
    func (pnd *pndImplementation) Request(uuid uuid.UUID, path string) error {
    
    	d, err := pnd.getDevice(uuid)
    	if err != nil {
    		return err
    	}
    
    	ctx := context.Background()
    
    	res, err := d.Transport.Get(ctx, path)
    	if err != nil {
    		return err
    	}
    	err = d.Transport.ProcessResponse(res, d.GoStruct, d.SBI.Schema())
    
    	if err != nil {
    		return err
    	}
    	return nil
    }
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // RequestAll sends a request for all registered devices
    
    func (pnd *pndImplementation) RequestAll(path string) error {
    
    	for _, k := range pnd.devices.UUIDs() {
    
    		if err := pnd.Request(k, path); err != nil {
    			return err
    		}
    	}
    
    	log.WithFields(log.Fields{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		"pnd":  pnd.id,
    
    		"path": path,
    	}).Info("sent request to all devices")
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    
    // Set sets the value to the given device path
    // TODO: Design commit/confirm mechanism
    func (pnd *pndImplementation) Set(uuid uuid.UUID, path string, value string) (interface{}, error) {
    	d, err := pnd.getDevice(uuid)
    	if err != nil {
    		return nil, err
    	}
    	ctx := context.Background()
    
    	// TODO: Move to transport dependent func
    	opts := []interface{}{
    		&gnmi.Operation{
    			Type:   "update",
    			Origin: "",
    			Target: "",
    			Path:   gnmi.SplitPath(path),
    			Val:    value,
    		},
    	}
    	return d.Transport.Set(ctx, opts...)
    }